Quellcode durchsuchen

feat(job): 实现AI自动审核任务功能

- 添加AI审核任务处理器AiCheckXxlJob
- 集成RestTemplate调用AI服务接口
- 实现用户违规记录的自动审核逻辑
- 支持从StoreImg表获取证据图片URL
- 更新LifeUserViolation状态及审核结果
- 优化HTTP请求拦截器添加认证头
- 修复查询条件以匹配正确的业务类型
zjy vor 1 Woche
Ursprung
Commit
99c227f5d9

+ 80 - 50
alien-job/src/main/java/shop/alien/job/second/AiCheckXxlJob.java

@@ -8,25 +8,28 @@ import com.xxl.job.core.context.XxlJobHelper;
 import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.client.ClientHttpRequestInterceptor;
 import org.springframework.stereotype.Component;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.http.*;
 import shop.alien.entity.result.R;
 import shop.alien.entity.second.SecondGoodsRecord;
 import shop.alien.entity.second.SecondRiskControlRecord;
-import shop.alien.entity.store.LifeUser;
-import shop.alien.entity.store.LifeUserViolation;
-import shop.alien.entity.store.StoreClockIn;
-import shop.alien.entity.store.StoreDictionary;
+import shop.alien.entity.store.*;
 import shop.alien.mapper.LifeUserMapper;
 import shop.alien.mapper.LifeUserViolationMapper;
 import shop.alien.mapper.StoreDictionaryMapper;
+import shop.alien.mapper.StoreImgMapper;
 import shop.alien.mapper.second.SecondGoodsRecordMapper;
 import shop.alien.mapper.second.SecondRiskControlRecordMapper;
+import shop.alien.util.common.Constants;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -44,6 +47,9 @@ import java.util.stream.Collectors;
 @Slf4j
 @Component
 @RequiredArgsConstructor
+//@RestController
+//@RequestMapping("/job")
+//@RequiredArgsConstructor
 public class AiCheckXxlJob {
 
     // 添加RestTemplate用于HTTP调用
@@ -59,6 +65,9 @@ public class AiCheckXxlJob {
 
     private final SecondRiskControlRecordMapper secondRiskControlRecordMapper;
 
+    @Autowired
+    private final StoreImgMapper storeImgMapper;
+
     // 第三方接口地址 登录接口URL
     @Value("${third-party-login.base-url}")
     private String loginUrl;
@@ -86,6 +95,7 @@ public class AiCheckXxlJob {
      * @since 1.0.0
      */
     @XxlJob("aiCheckJobHandler")
+//    @PostMapping("/aiCheckJobHandler")
     public void aiCheckJobHandler() {
         log.info("开始执行AI自动审核任务");
 
@@ -115,7 +125,9 @@ public class AiCheckXxlJob {
                     JSONObject dataJson = jsonObject.getJSONObject("data");
                     String accessToken = dataJson.getString("access_token");
                     // 查询所有待处理的用户违规记录
-                    List<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(new LambdaQueryWrapper<LifeUserViolation>().eq(LifeUserViolation::getProcessingStatus, "5"));
+                    List<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(new LambdaQueryWrapper<LifeUserViolation>()
+                            .eq(LifeUserViolation::getReportContextType, "4")
+                            .eq(LifeUserViolation::getProcessingStatus, "0"));
 
                     // 遍历每条违规记录,组装AI审核请求数据
                     for (LifeUserViolation violation : lifeUserViolations) {
@@ -140,7 +152,7 @@ public class AiCheckXxlJob {
                         requestBody.put("reporter_info", lifeUserMapper.selectById(violation.getReportingUserId()));
 
                         // 查询被举报的商品记录
-                        SecondGoodsRecord secondGoodsRecord = secondGoodsRecordMapper.selectById(violation.getGoodsId());
+                        SecondGoodsRecord secondGoodsRecord = secondGoodsRecordMapper.selectById(violation.getBusinessId());
                         if (secondGoodsRecord != null) {
                             // 设置被举报人信息
                             requestBody.put("reported_user_id", secondGoodsRecord.getUserId().toString());
@@ -155,8 +167,18 @@ public class AiCheckXxlJob {
                         // 设置投诉文本内容
                         requestBody.put("complaint_text", violation.getOtherReasonContent());
 
-                        // 设置证据图片数组(将逗号分隔的字符串转换为数组)
-                        requestBody.put("evidence_images", violation.getReportEvidenceImg() != null ? violation.getReportEvidenceImg().split(",") : new String[0]);
+                        LambdaQueryWrapper<StoreImg> wrapper = new LambdaQueryWrapper<>();
+                        wrapper.eq(StoreImg::getStoreId, violation.getId());
+                        wrapper.eq(StoreImg::getImgType, Constants.ImageType.SECOND_HAND_REPORT);
+                        List<StoreImg> imgList = storeImgMapper.selectList(wrapper);
+
+                        // 将 imgList 中的 ImgUrl 提取为 String[] 数组
+                        String[] imgUrls = imgList.stream()
+                                .map(StoreImg::getImgUrl)
+                                .toArray(String[]::new);
+
+                        // 设置证据图片数组
+                        requestBody.put("evidence_images", imgUrls);
 
                         HttpHeaders aiHeaders = new HttpHeaders();
                         aiHeaders.setContentType(MediaType.APPLICATION_JSON);
@@ -212,56 +234,64 @@ public class AiCheckXxlJob {
         } catch (Exception e) {
             log.error("请求AI服务登录接口失败", e);
         }
-        RestTemplate restTemplateWithAuth = new RestTemplate();
-        if (postForEntity != null && postForEntity.getStatusCodeValue() == 200) {
-            log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
-            String responseBody = postForEntity.getBody();
-            JSONObject jsonObject = JSONObject.parseObject(responseBody);
-            if (jsonObject != null) {
+
+        if (postForEntity != null) {
+            if (postForEntity.getStatusCodeValue() == 200) {
+                log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
+                String responseBody = postForEntity.getBody();
+                JSONObject jsonObject = JSONObject.parseObject(responseBody);
                 JSONObject dataJson = jsonObject.getJSONObject("data");
                 String accessToken = dataJson.getString("access_token");
-                List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
-                interceptors.add((request, body, execution) -> {
-                    request.getHeaders().set("Authorization", "Bearer " + accessToken);
-                    return execution.execute(request, body);
-                });
-                restTemplateWithAuth.setInterceptors(interceptors);
-            }
-        }
-        // 查询所有待处理的用户违规记录
-        List<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(new LambdaQueryWrapper<LifeUserViolation>().eq(LifeUserViolation::getProcessingStatus, "5"));
 
-        // 遍历每条违规记录,组装AI审核请求数据
-        for (LifeUserViolation violation : lifeUserViolations) {
-            // 针对已提交且未删除的动态轮询查询结果
-            try {
-                ResponseEntity<String> response = null;
-                try {
-                    response = restTemplateWithAuth.getForEntity("http://192.168.2.250:9100//api/v1/product_complaint_record/result/" + violation.getAiTaskId(), String.class);
-                    if (response.getStatusCodeValue() != 200) {
-                        log.error("AI内容审核结果获取接口调用失败 http状态:" + response.getStatusCode());
-                    }
-                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
-                    if (responseNode == null) {
-                        log.error("AI接口调用失败,响应内容为空");
-                    }
-                    Integer code = null;
-                    if (responseNode != null) {
-                        code = responseNode.getInteger("code");
-                        if (code == 200) {
-                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
-
-                        } else {
-                            log.error("AI接口调用失败,错误码: " + code);
+                // 查询所有待处理的用户违规记录
+                List<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(new LambdaQueryWrapper<LifeUserViolation>()
+                        .eq(LifeUserViolation::getReportContextType, "4")
+                        .eq(LifeUserViolation::getProcessingStatus, "0"));
+
+                for (LifeUserViolation violation : lifeUserViolations) {
+                    // 初始化请求体Map
+                    Map<String, Object> requestBody = new HashMap<>();
+
+                    // 设置投诉记录ID
+                    requestBody.put("task_id", violation.getAiTaskId());
+                    HttpHeaders aiHeaders = new HttpHeaders();
+                    aiHeaders.setContentType(MediaType.APPLICATION_JSON);
+                    aiHeaders.set("Authorization", "Bearer " + accessToken);
+
+                    System.out.println(requestBody);
+                    HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, aiHeaders);
+                    ResponseEntity<String> response = null;
+                    try {
+                        response = restTemplate.postForEntity("http://192.168.2.250:9000/ai/auto-review/api/v1/product_complaint_record/result", request, String.class);
+                        if (response.getStatusCodeValue() != 200) {
+                            throw new RuntimeException("AI门店审核接口调用失败 http状态:" + response.getStatusCode());
                         }
+                        if (StringUtils.isNotEmpty(response.getBody())) {
+                            com.alibaba.fastjson.JSONObject taskObject = com.alibaba.fastjson.JSONObject.parseObject(response.getBody());
+                            if (taskObject.getInteger("code") == 200) {
+                                com.alibaba.fastjson.JSONObject data = taskObject.getJSONObject("data");
+                                if (data != null) {
+                                    boolean isValid = data.getBoolean("is_valid");
+                                    String processingStatus;
+                                    if (isValid) {
+                                         processingStatus = "1";
+                                    } else {
+                                        processingStatus = "2";
+                                    }
+                                    violation.setReportResult(data.getString("matched_type"));
+                                    violation.setProcessingStatus(processingStatus);
+                                    lifeUserViolationMapper.updateById(violation);
+                                }
+                            }
+                        }
+                    } catch (Exception e) {
+                        log.error("AI自动审核结果查询异常", e);
                     }
-                } catch (Exception e) {
-                    log.error("调用AI内容审核结果获取接口失败", e);
+
                 }
-            }catch (RuntimeException ex){
-                XxlJobHelper.handleFail("动态内容审核任务执行失败:" + ex.getMessage());
             }
         }
+
     }
 
     /**

+ 7 - 7
alien-store/src/main/java/shop/alien/store/service/impl/LifeBlacklistServiceImpl.java

@@ -106,16 +106,16 @@ public class LifeBlacklistServiceImpl extends ServiceImpl<LifeBlacklistMapper, L
                 if ("1".equals(lifeBlacklist.getBlockedType())) {
                     StoreUser storeUser = storeUserMapper.selectById(lifeBlacklist.getBlockedId());
                     StoreImg storeImg = null;
-//                    if (storeUser != null) {
-//                        storeImg = storeImgMapper.selectOne(new LambdaUpdateWrapper<StoreImg>().eq(StoreImg::getStoreId, storeUser.getStoreId()).eq(StoreImg::getImgType, 10));
-//                    }
                     if (storeUser != null) {
-                        lifeBlacklist.setName(storeUser.getNickName());
+                        storeImg = storeImgMapper.selectOne(new LambdaUpdateWrapper<StoreImg>().eq(StoreImg::getStoreId, storeUser.getStoreId()).eq(StoreImg::getImgType, 10));
+                    }
+                    if (storeUser != null) {
+                        lifeBlacklist.setName(storeUser.getName());
                         lifeBlacklist.setPhoneId(storeUser.getPhone());
                         lifeBlacklist.setUserImage(storeUser.getHeadImg());
-//                        if (storeImg != null) {
-//                            lifeBlacklist.setUserImage(storeImg.getImgUrl());
-//                        }
+                        if (storeImg != null) {
+                            lifeBlacklist.setUserImage(storeImg.getImgUrl());
+                        }
                     }
                 } else {
                     LifeUser lifeUser = lifeUserMapper.selectById(lifeBlacklist.getBlockedId());