浏览代码

Merge remote-tracking branch 'origin/master'

linweichao 1 周之前
父节点
当前提交
500f24cb07
共有 52 个文件被更改,包括 1078 次插入187 次删除
  1. 16 38
      qnfhq-api/src/main/java/com/qnfhq/constant/CacheConstants.java
  2. 1 1
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cAdController.java
  3. 137 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cMsgContentController.java
  4. 3 8
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cOrderController.java
  5. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMsgContactDao.java
  6. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMsgContentDao.java
  7. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMsgRelationDao.java
  8. 27 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMsgContactDTO.java
  9. 50 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMsgContentDTO.java
  10. 35 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMsgRelationDTO.java
  11. 2 3
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainVoucherDTO.java
  12. 0 1
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderCreateDTO.java
  13. 25 1
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderDTO.java
  14. 0 2
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderIdDTO.java
  15. 0 3
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderListDTO.java
  16. 0 2
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPaymentVoucherIdDTO.java
  17. 53 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMsgContactEntity.java
  18. 49 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMsgContentEntity.java
  19. 42 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMsgRelationEntity.java
  20. 32 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/MsgRelationEnum.java
  21. 35 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/MsgStatusEnum.java
  22. 20 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/MsgTypeEnum.java
  23. 38 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMsgContactService.java
  24. 23 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMsgContentService.java
  25. 31 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMsgRelationService.java
  26. 0 2
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderComplainVoucherService.java
  27. 1 1
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderService.java
  28. 104 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMsgContactServiceImpl.java
  29. 62 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMsgContentServiceImpl.java
  30. 64 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMsgRelationServiceImpl.java
  31. 0 13
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderComplainVoucherServiceImpl.java
  32. 5 24
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderServiceImpl.java
  33. 0 26
      qnfhq-api/src/main/java/com/qnfhq/modules/user/controller/ApiAppUserController.java
  34. 1 5
      qnfhq-api/src/main/java/com/qnfhq/modules/user/service/AppUserService.java
  35. 0 47
      qnfhq-api/src/main/java/com/qnfhq/modules/user/service/impl/AppUserServiceImpl.java
  36. 4 1
      qnfhq-api/src/main/resources/i18n/messages_en.properties
  37. 3 0
      qnfhq-api/src/main/resources/i18n/messages_zh.properties
  38. 10 1
      qnfhq-api/src/main/resources/i18n/validation.properties
  39. 10 1
      qnfhq-api/src/main/resources/i18n/validation_de.properties
  40. 8 1
      qnfhq-api/src/main/resources/i18n/validation_en.properties
  41. 10 1
      qnfhq-api/src/main/resources/i18n/validation_es.properties
  42. 10 1
      qnfhq-api/src/main/resources/i18n/validation_fr.properties
  43. 10 1
      qnfhq-api/src/main/resources/i18n/validation_ja.properties
  44. 10 1
      qnfhq-api/src/main/resources/i18n/validation_ko.properties
  45. 9 0
      qnfhq-api/src/main/resources/i18n/validation_th.properties
  46. 10 1
      qnfhq-api/src/main/resources/i18n/validation_tw.properties
  47. 10 0
      qnfhq-api/src/main/resources/i18n/validation_vi.properties
  48. 8 1
      qnfhq-api/src/main/resources/i18n/validation_zh.properties
  49. 17 0
      qnfhq-api/src/main/resources/mapper/c2c/C2cMsgContactDao.xml
  50. 17 0
      qnfhq-api/src/main/resources/mapper/c2c/C2cMsgContentDao.xml
  51. 15 0
      qnfhq-api/src/main/resources/mapper/c2c/C2cMsgRelationDao.xml
  52. 13 0
      qnfhq-common/src/main/java/com/qnfhq/common/redis/RedisUtils.java

+ 16 - 38
qnfhq-api/src/main/java/com/qnfhq/constant/CacheConstants.java

@@ -104,19 +104,9 @@ public class CacheConstants
         return new StringBuilder("c2c_ad_h").append(adId).toString();
     }
 
-//    /**
-//     * 用户待支付数
-//     */
-//    public static final String C2C_UNPAY_COUNTS ="c2c-unpay-counts:{}";
-//
-//    /**
-//     * 用户待放币订单数
-//     */
-//    public static final String C2C_RELEASE_COUNTS ="c2c-release-counts:{}";
-//
-//    /**
-//     * 商家待支付数统计
-//     */
+    /**
+     * 商家待支付数统计
+     */
     public static String getC2cMertUnPayKey(String mertUid) {
         return new StringBuilder("c2c-mtunpay-counts:").append(mertUid).toString();
     }
@@ -129,31 +119,19 @@ public class CacheConstants
         return new StringBuilder("c2c-mtrelease-counts:").append(mertUid).toString();
     }
 
+    /**
+     * 聊天未读数key
+     */
+    public static String getChatUnreadKey(Long uid) {
+        return new StringBuilder("c2c-c-unread:").append(uid.toString()).toString();
+    }
+
+    /**
+     * 用户总未读数key
+     */
+    public static String getTotalUnreadKey(Long uid) {
+        return new StringBuilder("c2c-t-unread:").append(uid.toString()).toString();
+    }
 
 
-//    public static final BigDecimal AD_AVAIL_NUM_TOINT = new BigDecimal(100000000);
-//
-//    /**
-//     * 客服按会话数排序
-//     */
-//    public static final String KEFU_ZSET_KEY = "kefu_uids";
-//
-//    /**
-//     * 客服对应的会话
-//     */
-//    public static final String KEFU_SESSION_KEY = "session_";
-//
-//    /**
-//     * 客服信息
-//     */
-//    public static final String KEFU_INFO_KEY = "kefu_info_";
-//
-//    /**
-//     * 排队等待的用户
-//     */
-//    public static final String ONLINE_CUST_UID = "kefu_wait_uid";
-//    /**
-//     * 聊天的用户id
-//     */
-//    public static final String KEFU_UID_KEY = "im_uid_";
 }

+ 1 - 1
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cAdController.java

@@ -149,7 +149,7 @@ public class C2cAdController extends ApiBaseController {
         }
 
         Long adId = c2cAd.getId();
-        C2cAdEntity ad = c2cAdService.getById(adId);
+        C2cAdEntity ad = c2cAdService.selectById(adId);
         if(ad==null) {
             return error(MessageUtils.message("c2c.ad.id.invalid"));//广告编号无效
         }

+ 137 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cMsgContentController.java

@@ -0,0 +1,137 @@
+package com.qnfhq.modules.c2c.controller;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.map.MapUtil;
+import com.qnfhq.annotation.RepeatSubmit;
+import com.qnfhq.common.ApiBaseController;
+import com.qnfhq.common.constant.Constant;
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.redis.RedisUtils;
+import com.qnfhq.common.utils.MessageUtils;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.common.validator.ValidatorUtils;
+import com.qnfhq.constant.CacheConstants;
+import com.qnfhq.modules.c2c.dto.C2cMsgContactDTO;
+import com.qnfhq.modules.c2c.dto.C2cMsgContentDTO;
+import com.qnfhq.modules.c2c.dto.C2cMsgRelationDTO;
+import com.qnfhq.modules.c2c.entity.C2cMsgContactEntity;
+import com.qnfhq.modules.c2c.entity.C2cMsgRelationEntity;
+import com.qnfhq.modules.c2c.enums.MsgTypeEnum;
+import com.qnfhq.modules.c2c.service.C2cMsgContactService;
+import com.qnfhq.modules.c2c.service.C2cMsgContentService;
+import com.qnfhq.modules.c2c.service.C2cMsgRelationService;
+import com.qnfhq.modules.user.entity.AppUserEntity;
+import com.qnfhq.modules.user.service.AppUserService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import java.util.*;
+
+
+/**
+ * 聊天消息表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@RestController
+@RequestMapping("/c2cmsg")
+@Tag(name="c2c聊天接口")
+@Slf4j
+public class C2cMsgContentController extends ApiBaseController {
+    @Resource
+    private C2cMsgContentService c2cMsgContentService;
+
+    @Resource
+    private C2cMsgRelationService c2cMsgRelationService;
+
+    @Resource
+    private C2cMsgContactService c2cMsgContactService;
+    @Resource
+    private AppUserService appUserService;
+    @Resource
+    private RedisUtils redisUtils;
+
+    @PostMapping("/send")
+    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    @Operation(summary = "发消息")
+    public Result send(@RequestBody C2cMsgContentDTO dto){
+        //效验数据
+        ValidatorUtils.validateEntity(dto);
+
+        Long receptId = dto.getRecipientId();
+        AppUserEntity receptUser = appUserService.getById(receptId);
+        if(Objects.isNull(receptUser)) {
+            return new Result().error(MessageUtils.message("c2c.msg.receptId.notexists"));//"接收人不存在"
+        }
+
+        if(!MsgTypeEnum.isValid(dto.getMsgType())) {
+            return new Result().error(MessageUtils.message("c2c.msg.msgType.err"));//"消息类型错误"
+        }
+
+        if(receptId.longValue() == StpUtil.getLoginIdAsLong()) {
+            return new Result().error(MessageUtils.message("c2c.msg.receptId.err"));//不能给自己发消息
+        }
+
+        try {
+            return c2cMsgContentService.saveMsg(dto);
+        } catch (Exception e) {
+            log.error("c2cMsgContentService.saveMsg============"+e.getMessage(),e);
+            return new Result().error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+        }
+    }
+
+
+    @PostMapping("/chatList")
+    @Operation(summary = "查询与某人的聊天记录")
+    public Result<PageData<C2cMsgRelationEntity>> chatList(@RequestBody C2cMsgRelationDTO dto){
+        ValidatorUtils.validateEntity(dto);
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put(Constant.PAGE, dto.getPageNum());
+        params.put(Constant.LIMIT, dto.getPageSize());
+        params.put(Constant.ORDER_FIELD, "mid");
+        params.put(Constant.ORDER, "desc");
+        params.put("ownerUid", StpUtil.getLoginIdAsLong());
+        params.put("otherUid", dto.getOtherUid());
+        params.put("mid", dto.getMid());
+        PageData<C2cMsgRelationEntity> page = c2cMsgRelationService.selectChatPage(params);
+        page.getList().forEach(item -> item.setC2cMsg(c2cMsgContentService.getById(item.getMid())));
+
+        //聊天未读数更新
+        Long unreadC = Convert.toLong(redisUtils.hGet(CacheConstants.getChatUnreadKey(StpUtil.getLoginIdAsLong()), dto.getOtherUid().toString()),0L);
+        if(unreadC!=null && unreadC.longValue()>0) {
+            redisUtils.increment(CacheConstants.getChatUnreadKey(StpUtil.getLoginIdAsLong()), dto.getOtherUid().toString(), -unreadC.longValue(), -1L);
+            //总未读数更新
+            redisUtils.decrement(CacheConstants.getTotalUnreadKey(StpUtil.getLoginIdAsLong()), unreadC.longValue(), -1L);
+        }
+
+        return new Result<PageData<C2cMsgRelationEntity>>().ok(page);
+    }
+
+
+    @PostMapping("/contactList")
+    @Operation(summary = "查询我的最近联系人列表")
+    public Result<PageData<C2cMsgContactEntity>> contactList(@RequestBody C2cMsgContactDTO dto){
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put(Constant.PAGE, dto.getPageNum());
+        params.put(Constant.LIMIT, dto.getPageSize());
+        params.put(Constant.ORDER_FIELD, "mid");
+        params.put(Constant.ORDER, "desc");
+        params.put("ownerUid", StpUtil.getLoginIdAsLong());
+        PageData<C2cMsgContactEntity> page = c2cMsgContactService.selectContactPage(params);
+        page.getList().forEach(item -> {
+            item.setC2cMsg(c2cMsgContentService.getById(item.getMid()));
+            item.setUnreads(Convert.toLong(redisUtils.hGet(CacheConstants.getChatUnreadKey(item.getOwnerUid()), item.getOtherUid().toString()),0L));
+        });
+        //总未读数
+        Map data = MapUtil.of("totalUnread", Convert.toLong(redisUtils.get(CacheConstants.getTotalUnreadKey(StpUtil.getLoginIdAsLong())),0L));
+        data.put("page",page);
+        return new Result().ok(data);
+    }
+
+
+
+}

+ 3 - 8
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cOrderController.java

@@ -5,7 +5,6 @@ import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
-import com.alibaba.fastjson.JSON;
 import com.qnfhq.annotation.RepeatSubmit;
 import com.qnfhq.common.ApiBaseController;
 import com.qnfhq.common.constant.Constant;
@@ -36,7 +35,6 @@ import com.qnfhq.utils.DistributedRedisLock;
 import io.swagger.v3.oas.annotations.Operation;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -519,13 +517,11 @@ public class C2cOrderController extends ApiBaseController {
     @PostMapping("/mylist")
     public Result mylist(@RequestBody C2cOrderListDTO orderVo)
     {
-
         ValidatorUtils.validateEntity(orderVo);
         //分页
 //        Page<C2cOrderEntity> page = c2cOrderService.page(orderVo.getPage());
         String pageNum = Convert.toStr(orderVo.getPageNum(),"1");
         String pageSize = Convert.toStr(orderVo.getPageSize(),"10");
-
         Map<String,Object> params = new HashMap<>();
         params.put(Constant.PAGE,pageNum);
         params.put(Constant.LIMIT,pageSize);
@@ -536,10 +532,10 @@ public class C2cOrderController extends ApiBaseController {
         params.put("isMt",orderVo.getIsMt());
         PageData<C2cOrderEntity> page = c2cOrderService.page(params);
 
-        List<C2cOrderEntity> orderList = page.getRecords();
+        List<C2cOrderEntity> orderList = page.getList();
         // 查询付款凭证
         orderList = c2cOrderService.selectPaymentVoucherByOrderList(orderList);
-        page.setRecords(orderList);
+        page.setList(orderList);
 
         return new Result<>().ok(page);
 
@@ -622,8 +618,7 @@ public class C2cOrderController extends ApiBaseController {
     {
         ValidatorUtils.validateEntity(c2cOrderComplain);
 
-        C2cOrderEntity order = c2cOrderService.selectOrder(c2cOrderComplain.getOrderId());
-        log.info("订单信息:"+ JSON.toJSONString(order));
+        C2cOrderEntity order = c2cOrderService.selectById(c2cOrderComplain.getOrderId());
         if(order == null) {
             return error(MessageUtils.message("c2c.order.not.exist"));//订单编号无效
         }

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMsgContactDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cMsgContactEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 最近联系人
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Mapper
+public interface C2cMsgContactDao extends BaseDao<C2cMsgContactEntity> {
+	
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMsgContentDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cMsgContentEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 聊天消息表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Mapper
+public interface C2cMsgContentDao extends BaseDao<C2cMsgContentEntity> {
+	
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMsgRelationDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cMsgRelationEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 用户消息关联表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Mapper
+public interface C2cMsgRelationDao extends BaseDao<C2cMsgRelationEntity> {
+	
+}

+ 27 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMsgContactDTO.java

@@ -0,0 +1,27 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 最近联系人
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Data
+@Schema(name = "最近联系人")
+public class C2cMsgContactDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @SchemaProperty(name = "页码")
+    private String pageNum;
+
+    @SchemaProperty(name = "每页条数")
+    private String pageSize;
+}

+ 50 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMsgContentDTO.java

@@ -0,0 +1,50 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 聊天消息表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Data
+@Schema(name = "聊天消息表")
+public class C2cMsgContentDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @SchemaProperty(name = "消息编号")
+    private Long mid;
+
+	@SchemaProperty(name = "发送人编号")
+//    @NotNull(message="{NotBlank.senderId}")//发送人不能空
+	private Long senderId;
+
+	@SchemaProperty(name = "接收人编号")
+    @NotNull(message="{NotBlank.recipientId}")//接收人不能空
+	private Long recipientId;
+
+	@SchemaProperty(name = "消息内容")
+    @Length(min=1, max = 1000,message="{Length.content}")//消息内容长度不能超过1000
+    @NotBlank(message="{NotBlank.content}")//消息内容不能空
+	private String content;
+
+	@SchemaProperty(name = "消息类型: text 文本 image 图片 voice 语音 video 视频 location位置 ")
+    @NotBlank(message="{NotBlank.msgType}")//消息类型不能空
+	private String msgType;
+
+    @SchemaProperty(name = "0已发送 1已送达 2已读 3已撤回")
+    private Integer status;
+
+    @SchemaProperty(name = "发送时间")
+    private Date sendTime;
+}

+ 35 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMsgRelationDTO.java

@@ -0,0 +1,35 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 用户消息关联表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Data
+@Schema(name = "用户消息关联表")
+public class C2cMsgRelationDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "返回大于消息编号数据")
+	private Long mid;
+
+	@SchemaProperty(name = "对方编号")
+    @NotNull(message="{NotNull.otherUid}")//对方编号不能为空
+	private Long otherUid;
+
+    @SchemaProperty(name = "页码")
+    private String pageNum;
+
+    @SchemaProperty(name = "每页条数")
+    private String pageSize;
+}

+ 2 - 3
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainVoucherDTO.java

@@ -1,13 +1,12 @@
 package com.qnfhq.modules.c2c.dto;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.util.Date;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.media.SchemaProperty;
 
 /**
  * c2c申诉证明材料

+ 0 - 1
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderCreateDTO.java

@@ -8,7 +8,6 @@ import lombok.Data;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
-import java.util.Date;
 
 /**
  * c2c订单

+ 25 - 1
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderDTO.java

@@ -1,11 +1,16 @@
 package com.qnfhq.modules.c2c.dto;
 
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.qnfhq.modules.c2c.entity.C2cPaymentVoucherEntity;
+import com.qnfhq.modules.c2c.entity.C2cUserReceiptEntity;
 import lombok.Data;
 
 import java.io.Serializable;
 import java.util.Date;
 
 import java.math.BigDecimal;
+import java.util.List;
+
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.media.SchemaProperty;
 /**
@@ -19,7 +24,7 @@ import io.swagger.v3.oas.annotations.media.SchemaProperty;
 public class C2cOrderDTO implements Serializable {
     private static final long serialVersionUID = 1L;
 
-	@SchemaProperty(name = "")
+	@SchemaProperty(name = "自增编号")
 	private Long id;
 
 	@SchemaProperty(name = "订单编号")
@@ -61,6 +66,9 @@ public class C2cOrderDTO implements Serializable {
 	@SchemaProperty(name = "1微信  2支付宝 3银行借记卡")
 	private Integer payType;
 
+    @SchemaProperty(name = "付款时间")
+    private Date payTime;
+
 	@SchemaProperty(name = "0 进行中 1 已结束 ")
 	private Integer flow;
 
@@ -76,6 +84,22 @@ public class C2cOrderDTO implements Serializable {
 	@SchemaProperty(name = "")
 	private Date updateTime;
 
+    @SchemaProperty(name = "支付过期时间")
+    private Date payExpireTime;
+
+    @SchemaProperty(name = "完成时间")
+    private Date finishTime;
+
+    @SchemaProperty(name = "关闭时间")
+    private Date closeTime;
+
+    @SchemaProperty(name = "卖家收款信息")
+    C2cUserReceiptEntity receiptInfo;
+
+    @SchemaProperty(name = "是否有付款凭证")
+    Integer isVoucher=0;
 
+    @SchemaProperty(name = "买家付款凭证")
+    List<C2cPaymentVoucherEntity> payVoucherList;
 
 }

+ 0 - 2
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderIdDTO.java

@@ -6,8 +6,6 @@ import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.Date;
 
 /**
  * c2c订单

+ 0 - 3
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderListDTO.java

@@ -3,13 +3,10 @@ package com.qnfhq.modules.c2c.dto;
 import com.qnfhq.common.entity.BaseQueryDTO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.media.SchemaProperty;
-import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.Date;
 
 /**
  * c2c订单

+ 0 - 2
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPaymentVoucherIdDTO.java

@@ -2,12 +2,10 @@ package com.qnfhq.modules.c2c.dto;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.media.SchemaProperty;
-import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.util.Date;
 
 /**
  * c2c付款证明

+ 53 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMsgContactEntity.java

@@ -0,0 +1,53 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 最近联系人
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Data
+@TableName("c2c_msg_contact")
+public class C2cMsgContactEntity {
+
+    /**
+     * 
+     */
+	private Long ownerUid;
+    /**
+     * 
+     */
+	private Long otherUid;
+    /**
+     * 昵称
+     */
+	private String otherNickname;
+    /**
+     * 头像
+     */
+	private String otherAvatar;
+    /**
+     * 
+     */
+	private Long mid;
+    /**
+     * 消息类型: text 文本 image 图片 voice 语音 video 视频 location位置 
+     */
+	private String msgType;
+    /**
+     * 
+     */
+	private Date createTime;
+
+    @TableField(exist = false)
+    private C2cMsgContentEntity c2cMsg;
+
+    @TableField(exist = false)
+    private Long unreads;
+}

+ 49 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMsgContentEntity.java

@@ -0,0 +1,49 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 聊天消息表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Data
+@TableName("c2c_msg_content")
+public class C2cMsgContentEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long mid;
+    /**
+     * 
+     */
+	private Long senderId;
+    /**
+     * 
+     */
+	private Long recipientId;
+    /**
+     * 消息内容
+     */
+	private String content;
+    /**
+     * 消息类型: text 文本 image 图片 voice 语音 video 视频 location位置 链接link
+     */
+	private String msgType;
+    /**
+     * 0已发送 1已送达 2已读 3已撤回
+     */
+	private Integer status;
+    /**
+     * 
+     */
+	private Date sendTime;
+}

+ 42 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMsgRelationEntity.java

@@ -0,0 +1,42 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 用户消息关联表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Data
+@TableName("c2c_msg_relation")
+public class C2cMsgRelationEntity {
+
+    /**
+     * 
+     */
+	private Long mid;
+    /**
+     * 
+     */
+	private Long ownerUid;
+    /**
+     * 
+     */
+	private Long otherUid;
+    /**
+     * 类型 0发件箱 1收件箱
+     */
+	private Integer type;
+    /**
+     * 
+     */
+	private Date createTime;
+
+    @TableField(exist = false)
+    private C2cMsgContentEntity c2cMsg;
+}

+ 32 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/MsgRelationEnum.java

@@ -0,0 +1,32 @@
+package com.qnfhq.modules.c2c.enums;
+
+/**
+ * 一句话描述
+ *
+ * @Author: Yelz 30262728@qq.com
+ * @Date: 2025/11/26 06:17
+ * @Description:
+ */
+public enum MsgRelationEnum {
+    SEND_BOX(0,"发件箱"),
+    RECEIVE_BOX(1,"收件箱");
+
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getDesc()
+    {
+        return desc;
+    }
+
+    MsgRelationEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 35 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/MsgStatusEnum.java

@@ -0,0 +1,35 @@
+package com.qnfhq.modules.c2c.enums;
+
+/**
+ * 一句话描述
+ *
+ * @Author: Yelz 30262728@qq.com
+ * @Date: 2025/11/26 09:13
+ * @Description:
+ */
+public enum MsgStatusEnum {
+
+    SEND(0,"已发送"),
+    ARRIVED(1,"已送达"),
+    READ(2,"已读"),
+    REVOKE(3,"已撤回");
+
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getDesc()
+    {
+        return desc;
+    }
+
+    MsgStatusEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 20 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/MsgTypeEnum.java

@@ -0,0 +1,20 @@
+package com.qnfhq.modules.c2c.enums;
+
+
+public enum MsgTypeEnum {
+
+    TEXT,
+    IMAGE,
+    VOICE,
+    VIDEO,
+    LOCATION;
+
+    public static boolean isValid(String name) {
+        for (MsgTypeEnum em: MsgTypeEnum.values()) {
+            if (em.name().equals(name.toUpperCase())) {
+                return true;
+            }
+        }
+        return false;
+    }
+}

+ 38 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMsgContactService.java

@@ -0,0 +1,38 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.C2cMsgContactDTO;
+import com.qnfhq.modules.c2c.entity.C2cMsgContactEntity;
+import com.qnfhq.modules.c2c.entity.C2cMsgContentEntity;
+import java.util.Map;
+
+/**
+ * 最近联系人
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+public interface C2cMsgContactService extends BaseService<C2cMsgContactEntity> {
+    /**
+     * 最近联系人分页查询
+     * @param params
+     * @return
+     */
+    PageData<C2cMsgContactEntity> selectContactPage(Map<String, Object> params);
+
+    /**
+     * 查询最近联系人
+     * @param ownerUid
+     * @param otherUid
+     * @return
+     */
+    C2cMsgContactEntity selectByOwnerUidOtherUid(Long ownerUid, Long otherUid);
+
+    /**
+     * 保存最近联系人
+     * @param msgEntity
+     */
+    void saveByMsgContact(C2cMsgContentEntity msgEntity) throws Exception;
+}

+ 23 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMsgContentService.java

@@ -0,0 +1,23 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.modules.c2c.dto.C2cMsgContentDTO;
+import com.qnfhq.modules.c2c.entity.C2cMsgContentEntity;
+
+/**
+ * 聊天消息表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+public interface C2cMsgContentService extends IService<C2cMsgContentEntity> {
+
+    /**
+     * 保存消息
+     * @param dto
+     * @return
+     * @throws Exception
+     */
+    Result saveMsg(C2cMsgContentDTO dto) throws Exception;
+}

+ 31 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMsgRelationService.java

@@ -0,0 +1,31 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.C2cMsgRelationDTO;
+import com.qnfhq.modules.c2c.entity.C2cMsgContentEntity;
+import com.qnfhq.modules.c2c.entity.C2cMsgRelationEntity;
+
+import java.util.Map;
+
+/**
+ * 用户消息关联表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+public interface C2cMsgRelationService extends BaseService<C2cMsgRelationEntity> {
+    /**
+     * 查询用户聊天列表
+     * @param params
+     * @return
+     */
+    PageData<C2cMsgRelationEntity> selectChatPage(Map<String, Object> params);
+
+    /**
+     * 保存消息关联
+     * @param msgEntity
+     */
+    void saveMsgRelation(C2cMsgContentEntity msgEntity) throws Exception;
+}

+ 0 - 2
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderComplainVoucherService.java

@@ -1,8 +1,6 @@
 package com.qnfhq.modules.c2c.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.qnfhq.modules.c2c.dto.C2cOrderComplainVoucherDTO;
 import com.qnfhq.modules.c2c.entity.C2cOrderComplainVoucherEntity;
 
 import java.util.List;

+ 1 - 1
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderService.java

@@ -57,7 +57,7 @@ public interface C2cOrderService extends BaseService<C2cOrderEntity> {
      * @return
      * @throws Exception
      */
-    public Result createC2cOrder(C2cOrderCreateDTO c2cOrder, C2cAdEntity c2cAd,BigDecimal legalCoinAmount, BigDecimal symbolNum,
+    public Result createC2cOrder(C2cOrderCreateDTO c2cOrder, C2cAdEntity c2cAd, BigDecimal legalCoinAmount, BigDecimal symbolNum,
                                  Long loginUserId, String realName) throws Exception;
 
 

+ 104 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMsgContactServiceImpl.java

@@ -0,0 +1,104 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qnfhq.common.constant.Constant;
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cMsgContactDao;
+import com.qnfhq.modules.c2c.entity.C2cMsgContactEntity;
+import com.qnfhq.modules.c2c.entity.C2cMsgContentEntity;
+import com.qnfhq.modules.c2c.service.C2cMsgContactService;
+import com.qnfhq.modules.user.entity.AppUserEntity;
+import com.qnfhq.modules.user.service.AppUserService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import java.util.Date;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * 最近联系人
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Service
+public class C2cMsgContactServiceImpl extends BaseServiceImpl<C2cMsgContactDao, C2cMsgContactEntity> implements C2cMsgContactService {
+
+    @Resource
+    private AppUserService appUserService;
+
+
+    @Override
+    public PageData<C2cMsgContactEntity> selectContactPage(Map<String, Object> params) {
+        Long ownerUid = (Long)params.get("ownerUid");
+
+        LambdaQueryWrapper<C2cMsgContactEntity> wrapper = new LambdaQueryWrapper<C2cMsgContactEntity>()
+                .eq(Objects.nonNull(ownerUid),C2cMsgContactEntity::getOwnerUid, ownerUid);
+
+        IPage<C2cMsgContactEntity> page = baseDao.selectPage(
+                getPage(params, (String)params.get(Constant.ORDER_FIELD), "asc".equals(params.get(Constant.ORDER)) ? true : false),
+                wrapper
+        );
+        return getPageData(page, C2cMsgContactEntity.class);
+    }
+
+    @Override
+    public C2cMsgContactEntity selectByOwnerUidOtherUid(Long ownerUid, Long otherUid) {
+        LambdaQueryWrapper<C2cMsgContactEntity> wrapper = new LambdaQueryWrapper<C2cMsgContactEntity>()
+                .eq(Objects.nonNull(ownerUid),C2cMsgContactEntity::getOwnerUid, ownerUid)
+                .eq(Objects.nonNull(otherUid),C2cMsgContactEntity::getOtherUid, otherUid);
+        return baseDao.selectOne(wrapper);
+    }
+
+    private void updateByOwnerUidOtherUid(C2cMsgContactEntity contactEntity) throws Exception{
+        baseDao.update(contactEntity, new LambdaQueryWrapper<C2cMsgContactEntity>()
+                .eq(Objects.nonNull(contactEntity.getOwnerUid()),C2cMsgContactEntity::getOwnerUid, contactEntity.getOwnerUid())
+                .eq(Objects.nonNull(contactEntity.getOtherUid()),C2cMsgContactEntity::getOtherUid, contactEntity.getOtherUid()));
+    }
+
+
+    @Override
+    public void saveByMsgContact(C2cMsgContentEntity msgEntity) throws Exception{
+        AppUserEntity receiptUser = appUserService.getById(msgEntity.getRecipientId());
+        AppUserEntity senderUser = appUserService.getById(msgEntity.getSenderId());
+        // 更新发件人的最近联系人
+        C2cMsgContactEntity senderContact = selectByOwnerUidOtherUid(msgEntity.getSenderId(), msgEntity.getRecipientId());
+        if(senderContact!=null) {
+            senderContact.setMid(msgEntity.getMid());
+            senderContact.setMsgType(msgEntity.getMsgType());
+            senderContact.setCreateTime(new Date());
+            updateByOwnerUidOtherUid(senderContact);
+        } else {
+            senderContact = new C2cMsgContactEntity();
+            senderContact.setOwnerUid(msgEntity.getSenderId());
+            senderContact.setOtherUid(msgEntity.getRecipientId());
+            senderContact.setOtherNickname(receiptUser.getNickname());
+            senderContact.setOtherAvatar(receiptUser.getAvatar());
+            senderContact.setMid(msgEntity.getMid());
+            senderContact.setMsgType(msgEntity.getMsgType());
+            senderContact.setCreateTime(new Date());
+            insert(senderContact);
+        }
+
+        // 更新收件人的最近联系人
+        C2cMsgContactEntity receipterContact = selectByOwnerUidOtherUid(msgEntity.getRecipientId(),msgEntity.getSenderId());
+        if(receipterContact!=null) {
+            receipterContact.setMid(msgEntity.getMid());
+            receipterContact.setMsgType(msgEntity.getMsgType());
+            receipterContact.setCreateTime(new Date());
+            updateByOwnerUidOtherUid(receipterContact);
+        } else {
+            receipterContact = new C2cMsgContactEntity();
+            receipterContact.setOwnerUid(msgEntity.getRecipientId());
+            receipterContact.setOtherUid(msgEntity.getSenderId());
+            receipterContact.setOtherNickname(senderUser.getNickname());
+            receipterContact.setOtherAvatar(senderUser.getAvatar());
+            receipterContact.setMid(msgEntity.getMid());
+            receipterContact.setMsgType(msgEntity.getMsgType());
+            receipterContact.setCreateTime(new Date());
+            insert(receipterContact);
+        }
+    }
+}

+ 62 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMsgContentServiceImpl.java

@@ -0,0 +1,62 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qnfhq.common.redis.RedisUtils;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.constant.CacheConstants;
+import com.qnfhq.modules.c2c.dao.C2cMsgContentDao;
+import com.qnfhq.modules.c2c.dto.C2cMsgContentDTO;
+import com.qnfhq.modules.c2c.entity.C2cMsgContentEntity;
+import com.qnfhq.modules.c2c.enums.MsgStatusEnum;
+import com.qnfhq.modules.c2c.service.C2cMsgContactService;
+import com.qnfhq.modules.c2c.service.C2cMsgContentService;
+import com.qnfhq.modules.c2c.service.C2cMsgRelationService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import java.util.Date;
+
+/**
+ * 聊天消息表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Service
+public class C2cMsgContentServiceImpl extends ServiceImpl<C2cMsgContentDao, C2cMsgContentEntity> implements C2cMsgContentService {
+
+    @Resource
+    private C2cMsgRelationService c2cMsgRelationService;
+    @Resource
+    private C2cMsgContactService c2cMsgContactService;
+    @Resource
+    private RedisUtils redisUtils;
+
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result saveMsg(C2cMsgContentDTO dto) throws Exception{
+        C2cMsgContentEntity msgEntity = new C2cMsgContentEntity();
+        msgEntity.setSenderId(StpUtil.getLoginIdAsLong());
+        msgEntity.setRecipientId(dto.getRecipientId());
+        msgEntity.setContent(dto.getContent());
+        msgEntity.setMsgType(dto.getMsgType().toLowerCase());
+        msgEntity.setStatus(MsgStatusEnum.SEND.getCode());
+        msgEntity.setSendTime(new Date());
+        if(save(msgEntity)) {
+            // 保存消息关系
+            c2cMsgRelationService.saveMsgRelation(msgEntity);
+
+            // 保存最近联系人
+            c2cMsgContactService.saveByMsgContact(msgEntity);
+
+            //总未读数更新 2001534_UNREAD_T
+            redisUtils.increment(CacheConstants.getTotalUnreadKey(msgEntity.getRecipientId()), 1L,-1L);
+            //聊天用户未读数更新
+            redisUtils.increment(CacheConstants.getChatUnreadKey(msgEntity.getRecipientId()), msgEntity.getSenderId().toString(), 1L, -1L);
+        }
+        return new Result().ok(msgEntity);
+    }
+
+}

+ 64 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMsgRelationServiceImpl.java

@@ -0,0 +1,64 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qnfhq.common.constant.Constant;
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cMsgRelationDao;
+import com.qnfhq.modules.c2c.entity.C2cMsgContentEntity;
+import com.qnfhq.modules.c2c.entity.C2cMsgRelationEntity;
+import com.qnfhq.modules.c2c.enums.MsgRelationEnum;
+import com.qnfhq.modules.c2c.service.C2cMsgRelationService;
+import org.springframework.stereotype.Service;
+import java.util.*;
+
+/**
+ * 用户消息关联表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-25
+ */
+@Service
+public class C2cMsgRelationServiceImpl extends BaseServiceImpl<C2cMsgRelationDao, C2cMsgRelationEntity> implements C2cMsgRelationService {
+
+
+    @Override
+    public PageData<C2cMsgRelationEntity> selectChatPage(Map<String, Object> params) {
+        Long ownerUid = (Long)params.get("ownerUid");
+        Long otherUid = (Long)params.get("otherUid");
+        Long mid = (Long)params.get("mid");
+
+        LambdaQueryWrapper<C2cMsgRelationEntity> wrapper = new LambdaQueryWrapper<C2cMsgRelationEntity>()
+                .eq(Objects.nonNull(ownerUid),C2cMsgRelationEntity::getOwnerUid, ownerUid)
+                .eq(Objects.nonNull(otherUid),C2cMsgRelationEntity::getOtherUid, otherUid)
+                .gt(Objects.nonNull(mid),C2cMsgRelationEntity::getMid,mid);
+
+        IPage<C2cMsgRelationEntity> page = baseDao.selectPage(
+                getPage(params, (String)params.get(Constant.ORDER_FIELD), "asc".equals(params.get(Constant.ORDER)) ? true : false),
+                wrapper
+        );
+        return getPageData(page, C2cMsgRelationEntity.class);
+    }
+
+    @Override
+    public void saveMsgRelation(C2cMsgContentEntity msgEntity) throws Exception{
+        /**存发件人的发件箱*/
+        C2cMsgRelationEntity messageRelationSender = new C2cMsgRelationEntity();
+        messageRelationSender.setMid(msgEntity.getMid());
+        messageRelationSender.setOwnerUid(msgEntity.getSenderId());
+        messageRelationSender.setOtherUid(msgEntity.getRecipientId());
+        messageRelationSender.setType(MsgRelationEnum.SEND_BOX.getCode());
+        messageRelationSender.setCreateTime(new Date());
+        insert(messageRelationSender);
+
+        /**存收件人的收件箱*/
+        C2cMsgRelationEntity messageRelationRecipient = new C2cMsgRelationEntity();
+        messageRelationRecipient.setMid(msgEntity.getMid());
+        messageRelationRecipient.setOwnerUid(msgEntity.getRecipientId());
+        messageRelationRecipient.setOtherUid(msgEntity.getSenderId());
+        messageRelationRecipient.setType(MsgRelationEnum.RECEIVE_BOX.getCode());
+        messageRelationRecipient.setCreateTime(new Date());
+        insert(messageRelationRecipient);
+    }
+}

+ 0 - 13
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderComplainVoucherServiceImpl.java

@@ -2,16 +2,12 @@ package com.qnfhq.modules.c2c.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qnfhq.common.service.impl.CrudServiceImpl;
 import com.qnfhq.modules.c2c.dao.C2cOrderComplainVoucherDao;
-import com.qnfhq.modules.c2c.dto.C2cOrderComplainVoucherDTO;
 import com.qnfhq.modules.c2c.entity.C2cOrderComplainVoucherEntity;
 import com.qnfhq.modules.c2c.service.C2cOrderComplainVoucherService;
-import cn.hutool.core.util.StrUtil;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -23,15 +19,6 @@ import java.util.Objects;
 @Service
 public class C2cOrderComplainVoucherServiceImpl extends ServiceImpl<C2cOrderComplainVoucherDao, C2cOrderComplainVoucherEntity> implements C2cOrderComplainVoucherService {
 
-//    @Override
-//    public QueryWrapper<C2cOrderComplainVoucherEntity> getWrapper(Map<String, Object> params){
-//        String id = (String)params.get("id");
-//
-//        QueryWrapper<C2cOrderComplainVoucherEntity> wrapper = new QueryWrapper<>();
-//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
-//
-//        return wrapper;
-//    }
 
     @Override
     public List<C2cOrderComplainVoucherEntity> selectList(Long complainId) {

+ 5 - 24
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderServiceImpl.java

@@ -6,20 +6,15 @@ import cn.hutool.core.map.MapUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.qnfhq.common.constant.Constant;
 import com.qnfhq.common.page.PageData;
 import com.qnfhq.common.redis.RedisUtils;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qnfhq.common.service.impl.BaseServiceImpl;
-import com.qnfhq.common.service.impl.CrudServiceImpl;
 import com.qnfhq.common.utils.DateUtils;
 import com.qnfhq.common.utils.MessageUtils;
 import com.qnfhq.common.utils.Result;
 import com.qnfhq.constant.CacheConstants;
 import com.qnfhq.modules.c2c.dao.C2cOrderDao;
 import com.qnfhq.modules.c2c.dto.C2cOrderCreateDTO;
-import com.qnfhq.modules.c2c.dto.C2cOrderDTO;
-import com.qnfhq.modules.c2c.dto.C2cOrderLogDTO;
 import com.qnfhq.modules.c2c.entity.*;
 import com.qnfhq.modules.c2c.enums.*;
 import com.qnfhq.modules.c2c.service.*;
@@ -34,14 +29,11 @@ import com.qnfhq.modules.user.service.AppWalletRecordService;
 import com.qnfhq.utils.OrderUtils;
 import com.qnfhq.utils.RandomNumberGenerator;
 import jakarta.annotation.Resource;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.util.*;
-import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -130,16 +122,6 @@ public class C2cOrderServiceImpl extends BaseServiceImpl<C2cOrderDao, C2cOrderEn
     }
 
 
-//    @Override
-//    public QueryWrapper<C2cOrderEntity> getWrapper(Map<String, Object> params){
-//        String id = (String)params.get("id");
-//
-//        QueryWrapper<C2cOrderEntity> wrapper = new QueryWrapper<>();
-//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
-//
-//        return wrapper;
-//    }
-
     @Override
     public String getC2cOrderKeyByUid(String uid) {
         return new StringBuilder("c2c_order_uid:").append(uid).toString();
@@ -147,10 +129,9 @@ public class C2cOrderServiceImpl extends BaseServiceImpl<C2cOrderDao, C2cOrderEn
 
     @Override
     public C2cOrderEntity getTradingByAdId(long adId) {
-        return getOne(new LambdaQueryWrapper<C2cOrderEntity>()
+        return baseDao.selectOne(new LambdaQueryWrapper<C2cOrderEntity>()
                 .eq(C2cOrderEntity::getC2cAdId, adId)
                 .eq(C2cOrderEntity::getFlow, 0)
-                .last(" limit 1")
         );
     }
 
@@ -160,7 +141,7 @@ public class C2cOrderServiceImpl extends BaseServiceImpl<C2cOrderDao, C2cOrderEn
     public C2cOrderEntity selectOrder(Long id) {
         C2cOrderEntity order = selectOrderFromRedis(id);
         if(order == null) {
-            order = getById(id);
+            order = selectById(id);
             if(order == null) {
                 return null;
             }
@@ -266,7 +247,7 @@ public class C2cOrderServiceImpl extends BaseServiceImpl<C2cOrderDao, C2cOrderEn
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result createC2cOrder(C2cOrderCreateDTO c2cOrderDTO, C2cAdEntity c2cAd,BigDecimal legalCoinAmount, BigDecimal symbolNum,
+    public Result createC2cOrder(C2cOrderCreateDTO c2cOrderDTO, C2cAdEntity c2cAd, BigDecimal legalCoinAmount, BigDecimal symbolNum,
                                  Long loginUserId, String realName) throws Exception {
         /** 1买入  2 卖出 */
         Integer direction = c2cOrderDTO.getDirection();
@@ -383,7 +364,7 @@ public class C2cOrderServiceImpl extends BaseServiceImpl<C2cOrderDao, C2cOrderEn
     @Override
     public int cancelC2cOrderRedis(int oldStatus,C2cOrderEntity order) {
         //redis广告可用数量恢复
-        C2cAdEntity c2cAd = c2cAdService.getById(order.getC2cAdId());
+        C2cAdEntity c2cAd = c2cAdService.selectById(order.getC2cAdId());
         c2cAdService.deleteAdCache(c2cAd.getId(),c2cAd.getPayway().replaceAll("^,|,$", ""),c2cAd.getLegalCoin(),c2cAd.getSymbol(),c2cAd.getDirection());
         c2cAdService.setAdCache(c2cAd);
         deleteOrderCache(order);
@@ -465,7 +446,7 @@ public class C2cOrderServiceImpl extends BaseServiceImpl<C2cOrderDao, C2cOrderEn
                     info.getFrozen(),info.getFrozen().subtract(order.getSymbolNum()),"c2c订单取消解冻资产");
         }
         //广告可用数量恢复
-        C2cAdEntity c2cAd = c2cAdService.getById(order.getC2cAdId());
+        C2cAdEntity c2cAd = c2cAdService.selectById(order.getC2cAdId());
         BigDecimal maxAmount = null;
         if(order.getTranAmount().compareTo(c2cAd.getMaxAmount())==1) {
             maxAmount = order.getTranAmount();

+ 0 - 26
qnfhq-api/src/main/java/com/qnfhq/modules/user/controller/ApiAppUserController.java

@@ -136,32 +136,6 @@ public class ApiAppUserController {
     }
 
 
-
-
-    /**
-     * 重置登陆密码 old
-     *
-     * @return
-     */
-//    @PostMapping("/resetPwdByEmail")
-//    public Result resetPwdByEmail (@RequestBody ResetPwdByEmailDTO codeDTO){
-//        ValidatorUtils.validateEntity(codeDTO);
-//        return appUserService.resetPwdByEmail(codeDTO);
-//    }
-
-    /**
-     * 重置登陆密码 old
-     *
-     * @return
-     */
-//    @PostMapping("/resetPwdByPhone")
-//    public Result resetPwdByPhone (@RequestBody ResetPwdByPhoneDTO codeDTO){
-//        ValidatorUtils.validateEntity(codeDTO);
-//
-//        return appUserService.resetPwdByPhone(codeDTO);
-//    }
-
-
     @PostMapping("/checkCaptcha")
     @Operation(summary = "验证图形验证码")
     public Result checkCaptcha(@RequestBody CheckCaptchaDTO dto, HttpServletRequest request) {

+ 1 - 5
qnfhq-api/src/main/java/com/qnfhq/modules/user/service/AppUserService.java

@@ -69,12 +69,8 @@ public interface AppUserService extends IService<AppUserEntity> {
      */
     public Result sendMobileCode(String codeType,String phone,String zone);
 
-
-
-    Result resetPwdByEmail(ResetPwdByEmailDTO codeDTO);
-    Result resetPwdByPhone(ResetPwdByPhoneDTO codeDTO);
-
     AppUserDetailEntity selectUserDetailByUserId(Long userId);
+
     Result checkCaptcha(CheckCaptchaDTO dto, HttpServletRequest request);
 
     Result checkPhoneCode(String codeType,String zone,String phone,String code);

+ 0 - 47
qnfhq-api/src/main/java/com/qnfhq/modules/user/service/impl/AppUserServiceImpl.java

@@ -424,30 +424,6 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserDao, AppUserEntity> i
     }
 
 
-    /**
-     * 重设密码
-     *
-     * @param codeDTO
-     * @return
-     */
-    @Override
-    public Result resetPwdByEmail(ResetPwdByEmailDTO codeDTO) {
-        Result result = new Result();
-
-        //校验邮箱验证码
-        checkEmailCode("FIND_PASSWORD", codeDTO.getEmail(), codeDTO.getCode());
-
-        //更新密码
-        AppUserEntity appUser = getUserByEmail(codeDTO.getEmail());
-        if (Objects.isNull(appUser)) {
-            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
-        }
-        appUser.setLoginPassword(PasswordUtils.encode(codeDTO.getNewPwd()));
-        updateById(appUser);
-        return result;
-
-    }
-
 
     @Override
     public Result resetPwdByEmail(String email, String newPwd) {
@@ -512,29 +488,6 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserDao, AppUserEntity> i
         redisUtils.delete(codeResultKey);
     }
 
-    /**
-     * 重设密码
-     *
-     * @param codeDTO
-     * @return
-     */
-    @Override
-    public Result resetPwdByPhone(ResetPwdByPhoneDTO codeDTO) {
-        Result result = new Result();
-
-        //校验手机验证码
-        checkPhoneCode("FIND_PASSWORD", codeDTO.getZone(), codeDTO.getPhone(), codeDTO.getCode());
-
-        //更新密码
-        AppUserEntity appUser = getUserByMobile(codeDTO.getPhone(), codeDTO.getZone());
-        if (Objects.isNull(appUser)) {
-            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
-        }
-        appUser.setLoginPassword(PasswordUtils.encode(codeDTO.getNewPwd()));
-        updateById(appUser);
-        return result;
-
-    }
 
     @Override
     public AppUserDetailEntity selectUserDetailByUserId(Long userId) {

+ 4 - 1
qnfhq-api/src/main/resources/i18n/messages_en.properties

@@ -131,4 +131,7 @@ c2c.userReceipt.id.invalid=Invalid ID
 c2c.order.complainId.orderId.all.empty=Complaint ID and order ID cannot both be empty
 c2c.order.param.tranAmt.min=The amount must be greater than the advertisement minimum limit  
 c2c.order.param.tranAmt.max=The amount must be less than the advertisement maximum limit  
-c2c.order.param.tranAmt.over.avail=The transaction amount exceeds the available quantity of the advertisement
+c2c.order.param.tranAmt.over.avail=The transaction amount exceeds the available quantity of the advertisement
+c2c.msg.receptId.notexists=Recipient does not exist
+c2c.msg.msgType.err=Message type error
+c2c.msg.receptId.err=Cannot send message to yourself

+ 3 - 0
qnfhq-api/src/main/resources/i18n/messages_zh.properties

@@ -134,3 +134,6 @@ c2c.order.complainId.orderId.all.empty=\u7533\u8bc9\u7f16\u53f7\u3001\u8ba2\u535
 c2c.order.param.tranAmt.min=\u91d1\u989d\u5fc5\u987b\u5927\u4e8e\u5e7f\u544a\u6700\u5c0f\u9650\u989d
 c2c.order.param.tranAmt.max=\u91d1\u989d\u5fc5\u987b\u5c0f\u4e8e\u5e7f\u544a\u6700\u5927\u9650\u989d
 c2c.order.param.tranAmt.over.avail=\u4ea4\u6613\u91d1\u989d\u8d85\u8fc7\u5e7f\u544a\u53ef\u7528\u6570\u91cf
+c2c.msg.receptId.notexists=\u63a5\u6536\u4eba\u4e0d\u5b58\u5728
+c2c.msg.msgType.err=\u6d88\u606f\u7c7b\u578b\u9519\u8bef
+c2c.msg.receptId.err=\u4e0d\u80fd\u7ed9\u81ea\u5df1\u53d1\u6d88\u606f

+ 10 - 1
qnfhq-api/src/main/resources/i18n/validation.properties

@@ -35,4 +35,13 @@ NotBlank.reason=Alasan aduan tidak boleh kosong
 NotBlank.remark=Penerangan bukti tidak boleh kosong  
 NotBlank.img1=Tangkapan skrin bukti 1 tidak boleh kosong  
 NotNull.complainId=Nombor aduan tidak boleh kosong  
-NotBlank.country=Negara tidak boleh kosong
+NotBlank.country=Negara tidak boleh kosong
+NotNull.tag=Label tidak boleh kosong  
+NotNull.unit=Unit transaksi tidak boleh kosong  
+NotBlank.senderId=Pengirim tidak boleh kosong  
+NotBlank.recipientId=Penerima tidak boleh kosong  
+NotBlank.content=Kandungan mesej tidak boleh kosong  
+NotBlank.msgType=Jenis mesej tidak boleh kosong  
+NotNull.ownerUid=ID pengguna tidak boleh kosong  
+NotNull.otherUid=ID pihak lain tidak boleh kosong
+Length.content=Kandungan mesej tidak boleh melebihi 1000 panjang

+ 10 - 1
qnfhq-api/src/main/resources/i18n/validation_de.properties

@@ -35,4 +35,13 @@ NotBlank.reason=Beschwerdegrund darf nicht leer sein
 NotBlank.remark=Nachweisbeschreibung darf nicht leer sein  
 NotBlank.img1=Screenshot des Nachweises 1 darf nicht leer sein  
 NotNull.complainId=Beschwerde-ID darf nicht leer sein  
-NotBlank.country=Land darf nicht leer sein
+NotBlank.country=Land darf nicht leer sein
+NotNull.tag=Das Etikett darf nicht leer sein  
+NotNull.unit=Die Handelseinheit darf nicht leer sein  
+NotBlank.senderId=Absender darf nicht leer sein  
+NotBlank.recipientId=Empf\u00e4nger darf nicht leer sein  
+NotBlank.content=Nachrichteninhalt darf nicht leer sein  
+NotBlank.msgType=Nachrichtentyp darf nicht leer sein  
+NotNull.ownerUid=Benutzernummer darf nicht leer sein  
+NotNull.otherUid=Gegenseitige Nummer darf nicht leer sein
+Die L\u00e4nge des Nachrichteninhalts darf 1000 nicht \u00fcberschreiten.

+ 8 - 1
qnfhq-api/src/main/resources/i18n/validation_en.properties

@@ -38,4 +38,11 @@ NotNull.complainId=Appeal ID cannot be empty
 NotBlank.country=Country cannot be empty
 
 NotNull.tag=Tag cannot be empty
-NotNull.unit
+NotNull.unit=Transaction unit cannot be empty
+NotBlank.senderId=Sender cannot be empty
+NotBlank.recipientId=Recipient cannot be empty
+NotBlank.content=Message content cannot be empty
+NotBlank.msgType=Message type cannot be empty
+NotNull.ownerUid=User ID cannot be empty
+NotNull.otherUid=Counterparty ID cannot be empty
+Length.content=The length of the message content cannot exceed 1000

+ 10 - 1
qnfhq-api/src/main/resources/i18n/validation_es.properties

@@ -35,4 +35,13 @@ NotBlank.reason=La raz\u00f3n de la apelaci\u00f3n no puede estar vac\u00eda
 NotBlank.remark=La descripci\u00f3n del comprobante no puede estar vac\u00eda  
 NotBlank.img1=La captura del comprobante 1 no puede estar vac\u00eda  
 NotNull.complainId=El n\u00famero de apelaci\u00f3n no puede estar vac\u00edo  
-NotBlank.country=El pa\u00eds no puede estar vac\u00edo
+NotBlank.country=El pa\u00eds no puede estar vac\u00edo
+NotNull.tag=La etiqueta no puede estar vac\u00eda  
+NotNull.unit=La unidad de transacci\u00f3n no puede estar vac\u00eda  
+NotBlank.senderId=El remitente no puede estar vac\u00edo  
+NotBlank.recipientId=El destinatario no puede estar vac\u00edo  
+NotBlank.content=El contenido del mensaje no puede estar vac\u00edo  
+NotBlank.msgType=El tipo de mensaje no puede estar vac\u00edo  
+NotNull.ownerUid=El n\u00famero de usuario no puede estar vac\u00edo  
+NotNull.otherUid=El n\u00famero de la otra parte no puede estar vac\u00edo
+Length.content=La longitud del contenido del mensaje no puede exceder los 1000

+ 10 - 1
qnfhq-api/src/main/resources/i18n/validation_fr.properties

@@ -35,4 +35,13 @@ NotBlank.reason=La raison de la plainte ne peut pas \u00eatre vide
 NotBlank.remark=La description de la preuve ne peut pas \u00eatre vide  
 NotBlank.img1=La capture d'\u00e9cran de la preuve 1 ne peut pas \u00eatre vide  
 NotNull.complainId=Le num\u00e9ro de la plainte ne peut pas \u00eatre vide  
-NotBlank.country=Le pays ne peut pas \u00eatre vide
+NotBlank.country=Le pays ne peut pas \u00eatre vide
+NotNull.tag=Le tag ne peut pas \u00eatre vide  
+NotNull.unit=L'unit\u00e9 de transaction ne peut pas \u00eatre vide  
+NotBlank.senderId=L'exp\u00e9diteur ne peut pas \u00eatre vide  
+NotBlank.recipientId=Le destinataire ne peut pas \u00eatre vide  
+NotBlank.content=Le contenu du message ne peut pas \u00eatre vide  
+NotBlank.msgType=Le type de message ne peut pas \u00eatre vide  
+NotNull.ownerUid=Le num\u00e9ro d'utilisateur ne peut pas \u00eatre vide  
+NotNull.otherUid=Le num\u00e9ro de l'autre partie ne peut pas \u00eatre vide
+Length.content=La longueur du contenu du message ne peut pas d\u00e9passer 1000

+ 10 - 1
qnfhq-api/src/main/resources/i18n/validation_ja.properties

@@ -35,4 +35,13 @@ NotBlank.reason=\u7533\u7acb\u7406\u7531\u3092\u7a7a\u306b\u3067\u304d\u307e\u30
 NotBlank.remark=\u8a3c\u660e\u306e\u8aac\u660e\u3092\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
 NotBlank.img1=\u8a3c\u660e\u30b9\u30af\u30ea\u30fc\u30f3\u30b7\u30e7\u30c3\u30c81\u3092\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
 NotNull.complainId=\u7533\u7acb\u756a\u53f7\u3092\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
-NotBlank.country=\u56fd\u3092\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotBlank.country=\u56fd\u3092\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotNull.tag=\u30bf\u30b0\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotNull.unit=\u53d6\u5f15\u5358\u4f4d\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotBlank.senderId=\u9001\u4fe1\u8005\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotBlank.recipientId=\u53d7\u4fe1\u8005\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotBlank.content=\u30e1\u30c3\u30bb\u30fc\u30b8\u5185\u5bb9\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotBlank.msgType=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotNull.ownerUid=\u30e6\u30fc\u30b6\u30fc\u756a\u53f7\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+NotNull.otherUid=\u76f8\u624b\u756a\u53f7\u306f\u7a7a\u306b\u3067\u304d\u307e\u305b\u3093
+Length.content=\u30e1\u30c3\u30bb\u30fc\u30b8\u5185\u5bb9\u306e\u9577\u3055\u306f1000\u3092\u8d85\u3048\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093

+ 10 - 1
qnfhq-api/src/main/resources/i18n/validation_ko.properties

@@ -35,4 +35,13 @@ NotBlank.reason=\uc2e0\uace0 \uc0ac\uc720\ub294 \ube44\uc6cc\ub458 \uc218 \uc5c6
 NotBlank.remark=\uc99d\ube59 \uc124\uba85\uc740 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4  
 NotBlank.img1=\uc99d\ube59 \uc2a4\ud06c\ub9b0\uc0f71\uc740 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4  
 NotNull.complainId=\uc2e0\uace0 \ubc88\ud638\ub294 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4  
-NotBlank.country=\uad6d\uac00\ub294 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotBlank.country=\uad6d\uac00\ub294 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotNull.tag=\ud0dc\uadf8\ub294 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotNull.unit=\uac70\ub798 \ub2e8\uc704\ub294 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotBlank.senderId=\ubcf4\ub0b4\ub294 \uc0ac\ub78c\uc740 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotBlank.recipientId=\ubc1b\ub294 \uc0ac\ub78c\uc740 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotBlank.content=\uba54\uc2dc\uc9c0 \ub0b4\uc6a9\uc740 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotBlank.msgType=\uba54\uc2dc\uc9c0 \uc720\ud615\uc740 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotNull.ownerUid=\uc0ac\uc6a9\uc790 \ubc88\ud638\ub294 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+NotNull.otherUid=\uc0c1\ub300\ubc29 \ubc88\ud638\ub294 \ube44\uc6cc\ub458 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4
+Length.content=\uba54\uc2dc\uc9c0 \ub0b4\uc6a9 \uae38\uc774\ub294 1000\uc790\ub97c \ucd08\uacfc\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4

+ 9 - 0
qnfhq-api/src/main/resources/i18n/validation_th.properties

@@ -36,3 +36,12 @@ NotBlank.remark=\u0e04\u0e33\u0e2d\u0e18\u0e34\u0e1a\u0e32\u0e22\u0e2b\u0e25\u0e
 NotBlank.img1=\u0e20\u0e32\u0e1e\u0e2b\u0e25\u0e31\u0e01\u0e10\u0e32\u0e19\u0e17\u0e35\u0e48 1 \u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
 NotNull.complainId=\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02\u0e01\u0e32\u0e23\u0e23\u0e49\u0e2d\u0e07\u0e40\u0e23\u0e35\u0e22\u0e19\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
 NotBlank.country=\u0e1b\u0e23\u0e30\u0e40\u0e17\u0e28\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+NotNull.tag=\u0e41\u0e17\u0e47\u0e01\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+NotNull.unit=\u0e2b\u0e19\u0e48\u0e27\u0e22\u0e01\u0e32\u0e23\u0e0b\u0e37\u0e49\u0e2d\u0e02\u0e32\u0e22\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+NotBlank.senderId=\u0e1c\u0e39\u0e49\u0e2a\u0e48\u0e07\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+NotBlank.recipientId=\u0e1c\u0e39\u0e49\u0e23\u0e31\u0e1a\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+NotBlank.content=\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+NotBlank.msgType=\u0e1b\u0e23\u0e30\u0e40\u0e20\u0e17\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+NotNull.ownerUid=\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02\u0e1c\u0e39\u0e49\u0e43\u0e0a\u0e49\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+NotNull.otherUid=\u0e2b\u0e21\u0e32\u0e22\u0e40\u0e25\u0e02\u0e1d\u0e48\u0e32\u0e22\u0e15\u0e23\u0e07\u0e02\u0e49\u0e32\u0e21\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e27\u0e48\u0e32\u0e07
+Length.content=\u0e04\u0e27\u0e32\u0e21\u0e22\u0e32\u0e27\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e15\u0e49\u0e2d\u0e07\u0e44\u0e21\u0e48\u0e40\u0e01\u0e34\u0e19 1000

+ 10 - 1
qnfhq-api/src/main/resources/i18n/validation_tw.properties

@@ -35,4 +35,13 @@ NotBlank.reason=\u7533\u8a34\u539f\u56e0\u4e0d\u80fd\u70ba\u7a7a
 NotBlank.remark=\u6191\u8b49\u63cf\u8ff0\u4e0d\u80fd\u70ba\u7a7a
 NotBlank.img1=\u6191\u8b49\u622a\u57161\u4e0d\u80fd\u70ba\u7a7a
 NotNull.complainId=\u7533\u8a34\u7de8\u865f\u4e0d\u80fd\u70ba\u7a7a
-NotBlank.country=\u570b\u5bb6\u4e0d\u80fd\u70ba\u7a7a
+NotBlank.country=\u570b\u5bb6\u4e0d\u80fd\u70ba\u7a7a
+NotNull.tag=\u6a19\u7c64\u4e0d\u80fd\u70ba\u7a7a
+NotNull.unit=\u4ea4\u6613\u55ae\u4f4d\u4e0d\u80fd\u70ba\u7a7a
+NotBlank.senderId=\u767c\u9001\u4eba\u4e0d\u80fd\u7a7a
+NotBlank.recipientId=\u63a5\u6536\u4eba\u4e0d\u80fd\u7a7a
+NotBlank.content=\u6d88\u606f\u5167\u5bb9\u4e0d\u80fd\u7a7a
+NotBlank.msgType=\u6d88\u606f\u985e\u578b\u4e0d\u80fd\u7a7a
+NotNull.ownerUid=\u7528\u6236\u7de8\u865f\u4e0d\u80fd\u70ba\u7a7a
+NotNull.otherUid=\u5c0d\u65b9\u7de8\u865f\u4e0d\u80fd\u70ba\u7a7a
+Length.content=\u6d88\u606f\u5167\u5bb9\u9577\u5ea6\u4e0d\u80fd\u8d85\u904e1000

+ 10 - 0
qnfhq-api/src/main/resources/i18n/validation_vi.properties

@@ -36,3 +36,13 @@ NotBlank.remark=M\u00f4 t\u1ea3 b\u1eb1ng ch\u1ee9ng kh\u00f4ng \u0111\u01b0\u1e
 NotBlank.img1=\u1ea2nh ch\u1ee5p b\u1eb1ng ch\u1ee9ng 1 kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
 NotNull.complainId=M\u00e3 khi\u1ebfu n\u1ea1i kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
 NotBlank.country=Qu\u1ed1c gia kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+NotNull.tag=Th\u1ebb kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+NotNull.unit=\u0110\u01a1n v\u1ecb giao d\u1ecbch kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+NotBlank.senderId=Ng\u01b0\u1eddi g\u1eedi kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+NotBlank.recipientId=Ng\u01b0\u1eddi nh\u1eadn kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+NotBlank.content=N\u1ed9i dung tin nh\u1eafn kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+NotBlank.msgType=Lo\u1ea1i tin nh\u1eafn kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+NotNull.ownerUid=M\u00e3 ng\u01b0\u1eddi d\u00f9ng kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+NotNull.otherUid=M\u00e3 \u0111\u1ed1i ph\u01b0\u01a1ng kh\u00f4ng \u0111\u01b0\u1ee3c \u0111\u1ec3 tr\u1ed1ng
+Length.content=\u0110\u1ed9 d\u00e0i n\u1ed9i dung tin nh\u1eafn kh\u00f4ng \u0111\u01b0\u1ee3c v\u01b0\u1ee3t qu\u00e1 1000
+

+ 8 - 1
qnfhq-api/src/main/resources/i18n/validation_zh.properties

@@ -38,4 +38,11 @@ NotNull.complainId=\u7533\u8bc9\u7f16\u53f7\u4e0d\u80fd\u4e3a\u7a7a
 NotBlank.country=\u56fd\u5bb6\u4e0d\u80fd\u4e3a\u7a7a
 
 NotNull.tag=\u6807\u7b7e\u4e0d\u80fd\u4e3a\u7a7a
-NotNull.unit
+NotNull.unit=\u4ea4\u6613\u5355\u4f4d\u4e0d\u80fd\u4e3a\u7a7a
+NotBlank.senderId=\u53d1\u9001\u4eba\u4e0d\u80fd\u7a7a
+NotBlank.recipientId=\u63a5\u6536\u4eba\u4e0d\u80fd\u7a7a
+NotBlank.content=\u6d88\u606f\u5185\u5bb9\u4e0d\u80fd\u7a7a
+NotBlank.msgType=\u6d88\u606f\u7c7b\u578b\u4e0d\u80fd\u7a7a
+NotNull.ownerUid=\u7528\u6237\u7f16\u53f7\u4e0d\u80fd\u4e3a\u7a7a
+NotNull.otherUid=\u5bf9\u65b9\u7f16\u53f7\u4e0d\u80fd\u4e3a\u7a7a
+Length.content=\u6d88\u606f\u5185\u5bb9\u957f\u5ea6\u4e0d\u80fd\u8d85\u8fc71000

+ 17 - 0
qnfhq-api/src/main/resources/mapper/c2c/C2cMsgContactDao.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.qnfhq.modules.c2c.dao.C2cMsgContactDao">
+
+    <resultMap type="com.qnfhq.modules.c2c.entity.C2cMsgContactEntity" id="c2cMsgContactMap">
+        <result property="ownerUid" column="owner_uid"/>
+        <result property="otherUid" column="other_uid"/>
+        <result property="otherNickname" column="other_nickname"/>
+        <result property="otherAvatar" column="other_avatar"/>
+        <result property="mid" column="mid"/>
+        <result property="msgType" column="msg_type"/>
+        <result property="createTime" column="create_time"/>
+    </resultMap>
+
+
+</mapper>

+ 17 - 0
qnfhq-api/src/main/resources/mapper/c2c/C2cMsgContentDao.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.qnfhq.modules.c2c.dao.C2cMsgContentDao">
+
+    <resultMap type="com.qnfhq.modules.c2c.entity.C2cMsgContentEntity" id="c2cMsgContentMap">
+        <result property="mid" column="mid"/>
+        <result property="senderId" column="sender_id"/>
+        <result property="recipientId" column="recipient_id"/>
+        <result property="content" column="content"/>
+        <result property="msgType" column="msg_type"/>
+        <result property="status" column="status"/>
+        <result property="sendTime" column="send_time"/>
+    </resultMap>
+
+
+</mapper>

+ 15 - 0
qnfhq-api/src/main/resources/mapper/c2c/C2cMsgRelationDao.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.qnfhq.modules.c2c.dao.C2cMsgRelationDao">
+
+    <resultMap type="com.qnfhq.modules.c2c.entity.C2cMsgRelationEntity" id="c2cMsgRelationMap">
+        <result property="mid" column="mid"/>
+        <result property="ownerUid" column="owner_uid"/>
+        <result property="otherUid" column="other_uid"/>
+        <result property="type" column="type"/>
+        <result property="createTime" column="create_time"/>
+    </resultMap>
+
+
+</mapper>

+ 13 - 0
qnfhq-common/src/main/java/com/qnfhq/common/redis/RedisUtils.java

@@ -144,6 +144,19 @@ public class RedisUtils {
         return newVal;
     }
 
+    /**
+     * 自增
+     * @param key     缓存的键值
+     * @param delta   递增步长
+     */
+    public <T> long increment(final String key,final String hashKey, final long delta,final long expire) {
+        long newVal = redisTemplate.opsForHash().increment(key, hashKey, delta);
+        if (expire != NOT_EXPIRE) {
+            expire(key, expire);
+        }
+        return newVal;
+    }
+
     /**
      * 递减
      * @param key