liujie
2026-09-14 82a8bc62d5b9d5d607f6952329952b17eda2f0a0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package com.tourguide.modules.feedback.service;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tourguide.common.api.PageResponse;
import com.tourguide.common.exception.BusinessException;
import com.tourguide.modules.feedback.dto.UserFeedbackResponse;
import com.tourguide.modules.feedback.entity.UserFeedback;
import com.tourguide.modules.feedback.mapper.UserFeedbackMapper;
import com.tourguide.modules.user.entity.GuideUser;
import com.tourguide.modules.user.entity.MiniUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
 
@Service
public class UserFeedbackService {
    private static final Set<String> FEEDBACK_TYPES = new HashSet<String>(Arrays.asList("VISITOR", "GUIDE"));
    private final UserFeedbackMapper feedbackMapper;
 
    public UserFeedbackService(UserFeedbackMapper feedbackMapper) {
        this.feedbackMapper = feedbackMapper;
    }
 
    public PageResponse<UserFeedbackResponse> page(long page, long size, String feedbackType,
                                                    String mobile, Integer status,
                                                    LocalDate startDate, LocalDate endDate) {
        String normalizedType = normalizeFeedbackType(feedbackType);
        LambdaQueryWrapper<UserFeedback> query = new LambdaQueryWrapper<UserFeedback>()
                .eq(UserFeedback::getFeedbackType, normalizedType)
                .like(StringUtils.hasText(mobile), UserFeedback::getUserMobile, mobile == null ? null : mobile.trim())
                .eq(status != null, UserFeedback::getStatus, status)
                .ge(startDate != null, UserFeedback::getFeedbackAt, startDate == null ? null : startDate.atStartOfDay())
                .lt(endDate != null, UserFeedback::getFeedbackAt, endDate == null ? null : endDate.plusDays(1).atStartOfDay())
                .orderByAsc(UserFeedback::getStatus)
                .orderByDesc(UserFeedback::getFeedbackAt)
                .orderByDesc(UserFeedback::getId);
        Page<UserFeedback> result = feedbackMapper.selectPage(new Page<UserFeedback>(page, size), query);
        return new PageResponse<UserFeedbackResponse>(
                result.getRecords().stream().map(UserFeedbackResponse::new).collect(Collectors.toList()),
                result.getTotal(), result.getCurrent(), result.getSize());
    }
 
    public UserFeedbackResponse detail(Long id) {
        return new UserFeedbackResponse(requireFeedback(id));
    }
 
    @Transactional
    public UserFeedbackResponse createVisitor(MiniUser user, String content) {
        return create("VISITOR", user.getId(), resolveUserName(user), user.getMobile(), content);
    }
 
    @Transactional
    public UserFeedbackResponse createGuide(GuideUser guide, String content) {
        return create("GUIDE", guide.getId(), resolveUserName(guide), guide.getMobile(), content);
    }
 
    private UserFeedbackResponse create(String feedbackType, Long userId, String userName,
                                        String userMobile, String content) {
        UserFeedback feedback = new UserFeedback();
        feedback.setFeedbackNo(generateFeedbackNo());
        feedback.setFeedbackType(feedbackType);
        feedback.setUserId(userId);
        feedback.setUserName(userName);
        feedback.setUserMobile(userMobile);
        feedback.setContent(content.trim());
        feedback.setFeedbackAt(LocalDateTime.now());
        feedback.setStatus(0);
        feedbackMapper.insert(feedback);
        return new UserFeedbackResponse(feedback);
    }
 
    @Transactional
    public UserFeedbackResponse process(Long id, String result, Long processorId, String processorName) {
        UserFeedback feedback = requireFeedback(id);
        if (Integer.valueOf(1).equals(feedback.getStatus())) {
            throw new BusinessException(409, "该反馈已处理,请勿重复操作");
        }
        feedback.setStatus(1);
        feedback.setProcessResult(result.trim());
        feedback.setProcessedBy(processorId);
        feedback.setProcessedByName(processorName);
        feedback.setProcessedAt(LocalDateTime.now());
        feedbackMapper.updateById(feedback);
        return new UserFeedbackResponse(feedback);
    }
 
    private UserFeedback requireFeedback(Long id) {
        UserFeedback feedback = feedbackMapper.selectById(id);
        if (feedback == null) throw new BusinessException(404, "反馈不存在");
        return feedback;
    }
 
    private String normalizeFeedbackType(String feedbackType) {
        String normalizedType = StringUtils.hasText(feedbackType) ? feedbackType.trim().toUpperCase() : "VISITOR";
        if (!FEEDBACK_TYPES.contains(normalizedType)) throw new BusinessException(400, "反馈类型不正确");
        return normalizedType;
    }
 
    private String resolveUserName(MiniUser user) {
        if (StringUtils.hasText(user.getRealName())) return user.getRealName();
        if (StringUtils.hasText(user.getNickname())) return user.getNickname();
        return user.getUsername();
    }
 
    private String resolveUserName(GuideUser guide) {
        if (StringUtils.hasText(guide.getRealName())) return guide.getRealName();
        return guide.getUsername();
    }
 
    private String generateFeedbackNo() {
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
        String random = UUID.randomUUID().toString().replace("-", "").substring(0, 5).toUpperCase();
        return "FB" + time + random;
    }
}