|
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.BeanUtils;
|
|
import org.springframework.beans.BeanUtils;
|
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
import org.springframework.util.CollectionUtils;
|
|
|
import org.springframework.util.ObjectUtils;
|
|
import org.springframework.util.ObjectUtils;
|
|
@@ -36,6 +37,10 @@ import java.util.stream.Collectors;
|
|
|
@RequiredArgsConstructor
|
|
@RequiredArgsConstructor
|
|
|
public class LifeCommentService {
|
|
public class LifeCommentService {
|
|
|
|
|
|
|
|
|
|
+ /** App 点击推送后跳转页面(uni-app 页面路径) */
|
|
|
|
|
+ private static final String DYNAMICS_LIKE_PUSH_OPEN_PATH =
|
|
|
|
|
+ "pages/secondHandTransactions/pages/message/noticesAndMessage";
|
|
|
|
|
+
|
|
|
private final LifeCommentMapper lifeCommentMapper;
|
|
private final LifeCommentMapper lifeCommentMapper;
|
|
|
|
|
|
|
|
private final StoreCommentMapper storeCommentMapper;
|
|
private final StoreCommentMapper storeCommentMapper;
|
|
@@ -64,6 +69,18 @@ public class LifeCommentService {
|
|
|
|
|
|
|
|
private final LifeUserPersonalizationSettingService lifeUserPersonalizationSettingService;
|
|
private final LifeUserPersonalizationSettingService lifeUserPersonalizationSettingService;
|
|
|
|
|
|
|
|
|
|
+ private final LifeUserPushDeviceService lifeUserPushDeviceService;
|
|
|
|
|
+
|
|
|
|
|
+ private final UniPushCloudInvokeService uniPushCloudInvokeService;
|
|
|
|
|
+
|
|
|
|
|
+ private final StoreUserMapper storeUserMapper;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 系统app通知开关
|
|
|
|
|
+ */
|
|
|
|
|
+ @Value("${alien.unipush.enabled:false}")
|
|
|
|
|
+ private boolean uniPushOn;
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 点赞操作
|
|
* 点赞操作
|
|
|
* <p>
|
|
* <p>
|
|
@@ -123,13 +140,28 @@ public class LifeCommentService {
|
|
|
// 根据类型更新对应表的点赞数
|
|
// 根据类型更新对应表的点赞数
|
|
|
int updateResult = updateLikeCountByType(huifuId, type);
|
|
int updateResult = updateLikeCountByType(huifuId, type);
|
|
|
|
|
|
|
|
- // 如果是动态类型,按点赞用户个性化设置决定是否发送通知
|
|
|
|
|
|
|
+ // 动态点赞:按「被点赞动态的发布者」的个性化设置决定是否通知(接收方是否愿意收点赞类通知)
|
|
|
if (updateResult > 0 && CommonConstant.LIKE_TYPE_DYNAMICS.equals(type)) {
|
|
if (updateResult > 0 && CommonConstant.LIKE_TYPE_DYNAMICS.equals(type)) {
|
|
|
- Integer likerLifeUserId = resolveLifeUserIdFromLikeParam(userId);
|
|
|
|
|
- boolean suppressNotice = likerLifeUserId != null
|
|
|
|
|
- && lifeUserPersonalizationSettingService.shouldSuppressLikeRelatedNotice(likerLifeUserId);
|
|
|
|
|
|
|
+ Integer receiverLifeUserId = resolveLifeUserIdFromDynamicsAuthorPhoneId(huifuId);
|
|
|
|
|
+ boolean suppressNotice = receiverLifeUserId != null
|
|
|
|
|
+ && lifeUserPersonalizationSettingService.shouldSuppressLikeRelatedNotice(receiverLifeUserId);
|
|
|
if (!suppressNotice) {
|
|
if (!suppressNotice) {
|
|
|
- insertNotice(userId, huifuId, type);
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ insertNotice(userId, huifuId, type);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("动态点赞站内信保存失败, huifuId={}", huifuId, e);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 发送系统通知开关
|
|
|
|
|
+ if(uniPushOn){
|
|
|
|
|
+ try {
|
|
|
|
|
+ sendDynamicsLikeAppPushByDynamicsId(Integer.parseInt(huifuId.trim()));
|
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
|
+ log.warn("动态点赞 App 推送跳过:huifuId 非合法动态 id, huifuId={}", huifuId);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("动态点赞 App 推送失败, huifuId={}, err={}", huifuId, e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -219,15 +251,23 @@ public class LifeCommentService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 点赞接口传入的 userId(字符串)解析为 life_user.id:纯数字按主键;user_ 前缀按手机号查用户
|
|
|
|
|
|
|
+ * 根据动态主键查发布者 phoneId,仅当为 C 端 user_ 前缀时解析为 life_user.id;门店动态 store_ 无 C 端个性化表则返回 null(不拦截通知)。
|
|
|
*/
|
|
*/
|
|
|
- private Integer resolveLifeUserIdFromLikeParam(String likeUserId) {
|
|
|
|
|
- if (!StringUtils.hasText(likeUserId)) {
|
|
|
|
|
|
|
+ private Integer resolveLifeUserIdFromDynamicsAuthorPhoneId(String dynamicsIdStr) {
|
|
|
|
|
+ if (!StringUtils.hasText(dynamicsIdStr)) {
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
- String trimmed = likeUserId.trim();
|
|
|
|
|
- if (trimmed.startsWith("user_")) {
|
|
|
|
|
- String phone = trimmed.substring("user_".length());
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ int dynamicsId = Integer.parseInt(dynamicsIdStr.trim());
|
|
|
|
|
+ LifeUserDynamics dynamics = lifeUserDynamicsMapper.selectById(dynamicsId);
|
|
|
|
|
+ if (dynamics == null || !StringUtils.hasText(dynamics.getPhoneId())) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ String phoneId = dynamics.getPhoneId().trim();
|
|
|
|
|
+ if (!phoneId.startsWith("user_")) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ String phone = phoneId.substring("user_".length());
|
|
|
if (!StringUtils.hasText(phone)) {
|
|
if (!StringUtils.hasText(phone)) {
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
@@ -236,9 +276,6 @@ public class LifeCommentService {
|
|
|
.eq(LifeUser::getDeleteFlag, 0)
|
|
.eq(LifeUser::getDeleteFlag, 0)
|
|
|
.last("LIMIT 1"));
|
|
.last("LIMIT 1"));
|
|
|
return u != null ? u.getId() : null;
|
|
return u != null ? u.getId() : null;
|
|
|
- }
|
|
|
|
|
- try {
|
|
|
|
|
- return Integer.parseInt(trimmed);
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
} catch (NumberFormatException e) {
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
@@ -262,6 +299,63 @@ public class LifeCommentService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
|
+ * 仅发起 App 推送(uniCloud),与 {@link #insertNotice} 独立;未配置、无 cid 时静默返回。
|
|
|
|
|
+ */
|
|
|
|
|
+ private void sendDynamicsLikeAppPushByDynamicsId(int dynamicsId) {
|
|
|
|
|
+ LifeUserDynamics dynamics = lifeUserDynamicsMapper.selectById(dynamicsId);
|
|
|
|
|
+ sendDynamicsLikeAppPushOnly(dynamics, "动态通知", "点赞了你的动态", dynamicsId);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void sendDynamicsLikeAppPushOnly(LifeUserDynamics dynamics, String title, String content, int dynamicsId) {
|
|
|
|
|
+ if (dynamics == null || !StringUtils.hasText(dynamics.getPhoneId())) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ String phoneId = dynamics.getPhoneId().trim();
|
|
|
|
|
+ List<String> cids = resolvePushClientIdsForDynamicsAuthor(phoneId);
|
|
|
|
|
+ if (CollectionUtils.isEmpty(cids)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> payload = new HashMap<>(12);
|
|
|
|
|
+ payload.put("scene", "dynamics_like");
|
|
|
|
|
+ payload.put("dynamicsId", dynamicsId);
|
|
|
|
|
+ payload.put("noticeType", 0);
|
|
|
|
|
+ payload.put("path", DYNAMICS_LIKE_PUSH_OPEN_PATH);
|
|
|
|
|
+ uniPushCloudInvokeService.sendToClientIds(cids, title, content, payload);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<String> resolvePushClientIdsForDynamicsAuthor(String phoneId) {
|
|
|
|
|
+ if (phoneId.startsWith("user_")) {
|
|
|
|
|
+ String phone = phoneId.substring("user_".length());
|
|
|
|
|
+ if (!StringUtils.hasText(phone)) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ LifeUser u = lifeUserMapper.selectOne(new LambdaQueryWrapper<LifeUser>()
|
|
|
|
|
+ .eq(LifeUser::getUserPhone, phone)
|
|
|
|
|
+ .eq(LifeUser::getDeleteFlag, 0)
|
|
|
|
|
+ .last("LIMIT 1"));
|
|
|
|
|
+ if (u == null) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ return lifeUserPushDeviceService.listPushClientIdsByUserId(u.getId(), PushDeviceOwnerType.USER.getCode());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (phoneId.startsWith("store_")) {
|
|
|
|
|
+ String phone = phoneId.substring("store_".length());
|
|
|
|
|
+ if (!StringUtils.hasText(phone)) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ StoreUser su = storeUserMapper.selectOne(new LambdaQueryWrapper<StoreUser>()
|
|
|
|
|
+ .eq(StoreUser::getPhone, phone)
|
|
|
|
|
+ .eq(StoreUser::getDeleteFlag, 0)
|
|
|
|
|
+ .last("LIMIT 1"));
|
|
|
|
|
+ if (su == null) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ return lifeUserPushDeviceService.listPushClientIdsByUserId(su.getId(), PushDeviceOwnerType.STORE.getCode());
|
|
|
|
|
+ }
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
* 取消点赞操作
|
|
* 取消点赞操作
|
|
|
* <p>
|
|
* <p>
|
|
|
* 检查是否已点赞,如果已点赞则删除点赞记录并更新对应表的点赞数
|
|
* 检查是否已点赞,如果已点赞则删除点赞记录并更新对应表的点赞数
|