|
|
@@ -1,19 +1,217 @@
|
|
|
package shop.alien.job.second;
|
|
|
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.xxl.job.core.handler.annotation.XxlJob;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.util.LinkedMultiValueMap;
|
|
|
+import org.springframework.util.MultiValueMap;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
+import org.springframework.http.*;
|
|
|
+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.StoreDictionary;
|
|
|
+import shop.alien.mapper.LifeUserMapper;
|
|
|
+import shop.alien.mapper.LifeUserViolationMapper;
|
|
|
+import shop.alien.mapper.StoreDictionaryMapper;
|
|
|
+import shop.alien.mapper.second.SecondGoodsRecordMapper;
|
|
|
+import shop.alien.mapper.second.SecondRiskControlRecordMapper;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* @author Lhaibo
|
|
|
* @date 2025/11/28
|
|
|
- * @since 1.0.0
|
|
|
* @desc: xxl-job
|
|
|
* AI调用审核任务
|
|
|
+ * @since 1.0.0
|
|
|
*/
|
|
|
@Slf4j
|
|
|
@Component
|
|
|
@RequiredArgsConstructor
|
|
|
public class AiCheckXxlJob {
|
|
|
|
|
|
+ // 添加RestTemplate用于HTTP调用
|
|
|
+ private final RestTemplate restTemplate;
|
|
|
+
|
|
|
+ private final LifeUserViolationMapper lifeUserViolationMapper;
|
|
|
+
|
|
|
+ private final StoreDictionaryMapper storeDictionaryMapper;
|
|
|
+
|
|
|
+ private final LifeUserMapper lifeUserMapper;
|
|
|
+
|
|
|
+ private final SecondGoodsRecordMapper secondGoodsRecordMapper;
|
|
|
+
|
|
|
+ private final SecondRiskControlRecordMapper secondRiskControlRecordMapper;
|
|
|
+
|
|
|
+ // 第三方接口地址 登录接口URL
|
|
|
+ @Value("${third-party-login.base-url}")
|
|
|
+ private String loginUrl;
|
|
|
+
|
|
|
+ //用户名
|
|
|
+ @Value("${third-party-user-name.base-url}")
|
|
|
+ private String userName;
|
|
|
+
|
|
|
+ //密码
|
|
|
+ @Value("${third-party-pass-word.base-url}")
|
|
|
+ private String passWord;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * AI自动审核任务处理器
|
|
|
+ * <p>
|
|
|
+ * 定时任务方法,用于批量处理用户违规举报记录,通过AI接口进行自动审核。
|
|
|
+ * 主要流程:
|
|
|
+ * 1. 查询所有待处理的用户违规记录
|
|
|
+ * 2. 遍历每条记录,组装审核请求数据
|
|
|
+ * 3. 调用AI审核接口进行自动审核(当前代码中已准备请求体,待实现接口调用)
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @author Lhaibo
|
|
|
+ * @date 2025/11/28
|
|
|
+ * @since 1.0.0
|
|
|
+ */
|
|
|
+ @XxlJob("aiCheckJobHandler")
|
|
|
+ public void aiCheckJobHandler() {
|
|
|
+ log.info("开始执行AI自动审核任务");
|
|
|
+
|
|
|
+ try {
|
|
|
+ log.info("登录Ai服务获取token..." + loginUrl);
|
|
|
+ //构建请求参数
|
|
|
+ MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
|
|
+ formData.add("username", "admin"); // 表单字段 1:用户名
|
|
|
+ formData.add("password", "123456"); // 表单字段 2:密码
|
|
|
+
|
|
|
+ //设置请求头
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
|
|
+ HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
|
|
|
+ ResponseEntity<String> postForEntity = null;
|
|
|
+ try {
|
|
|
+ postForEntity = restTemplate.postForEntity("http://192.168.2.78:9000/ai/user-auth-core/api/v1/auth/login", requestEntity, String.class);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("类:PostMethod 方法:post", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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<LifeUserViolation> lifeUserViolations = lifeUserViolationMapper.selectList(new LambdaQueryWrapper<LifeUserViolation>().eq(LifeUserViolation::getProcessingStatus, "5"));
|
|
|
+
|
|
|
+ // 遍历每条违规记录,组装AI审核请求数据
|
|
|
+ for (LifeUserViolation violation : lifeUserViolations) {
|
|
|
+ // 初始化请求体Map
|
|
|
+ Map<String, Object> requestBody = new HashMap<>();
|
|
|
+
|
|
|
+ // 设置投诉记录ID
|
|
|
+ requestBody.put("complaint_id", violation.getId());
|
|
|
+
|
|
|
+ // 查询投诉类型字典信息
|
|
|
+ StoreDictionary storeDictionary = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>()
|
|
|
+ .eq(StoreDictionary::getTypeName, violation.getDictId()).eq(StoreDictionary::getTypeName, violation.getDictType()));
|
|
|
+ String complaint_type = "";
|
|
|
+ if (storeDictionary != null) {
|
|
|
+ // 设置投诉类型
|
|
|
+ complaint_type = storeDictionary.getDictDetail();
|
|
|
+ }
|
|
|
+ requestBody.put("complaint_type", complaint_type);
|
|
|
+ // 设置举报人信息
|
|
|
+ requestBody.put("reporter_user_id", violation.getReportingUserId());
|
|
|
+ requestBody.put("reporter_user_type", violation.getReportingUserType());
|
|
|
+ requestBody.put("reporter_info", lifeUserMapper.selectById(violation.getReportingUserId()));
|
|
|
+
|
|
|
+ // 查询被举报的商品记录
|
|
|
+ SecondGoodsRecord secondGoodsRecord = secondGoodsRecordMapper.selectById(violation.getBusinessId());
|
|
|
+ if (secondGoodsRecord != null) {
|
|
|
+ // 设置被举报人信息
|
|
|
+ requestBody.put("reported_user_id", secondGoodsRecord.getUserId());
|
|
|
+ requestBody.put("reported_user_type", "");
|
|
|
+ requestBody.put("reported_info", lifeUserMapper.selectById(secondGoodsRecord.getUserId()));
|
|
|
+ requestBody.put("product_name", secondGoodsRecord.getTitle());
|
|
|
+ }
|
|
|
+ // 设置商品相关信息
|
|
|
+ requestBody.put("product_info", secondGoodsRecord);
|
|
|
+ requestBody.put("product_id", violation.getBusinessId());
|
|
|
+
|
|
|
+ // 设置投诉文本内容
|
|
|
+ requestBody.put("complaint_text", violation.getOtherReasonContent());
|
|
|
+
|
|
|
+ // 设置证据图片数组(将逗号分隔的字符串转换为数组)
|
|
|
+ requestBody.put("evidence_images", violation.getReportEvidenceImg() != null ? violation.getReportEvidenceImg().split(",") : new String[0]);
|
|
|
+
|
|
|
+ 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.78:9000/ai/auto-review/api/v1/product_complaint_record/submit", request, String.class);
|
|
|
+ log.info("AI自动审核结果:{}", response.getBody());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("AI自动审核请求异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("AI自动审核任务执行异常", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("AI自动审核任务执行完成");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 二手商品风控记录审核任务
|
|
|
+ * <p>
|
|
|
+ * 定时查询风控记录表中待处理的数据(risk_status = 0),
|
|
|
+ * 预留后续风控审核/处理逻辑(如调用 AI 服务、通知运营等)。
|
|
|
+ * </p>
|
|
|
+ */
|
|
|
+ @XxlJob("riskControlCheckJobHandler")
|
|
|
+ public void riskControlCheckJobHandler() {
|
|
|
+ log.info("开始执行二手商品风控记录审核任务");
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 查询风控记录表中待处理的记录(risk_status = 0)
|
|
|
+ List<SecondRiskControlRecord> riskControlRecords = secondRiskControlRecordMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<SecondRiskControlRecord>()
|
|
|
+ .eq(SecondRiskControlRecord::getRiskStatus, 0)
|
|
|
+ );
|
|
|
+
|
|
|
+ log.info("本次待处理风控记录数量:{}", riskControlRecords.size());
|
|
|
+
|
|
|
+ // 按 ruleType 和 businessId 进行分组,生成新的嵌套结构
|
|
|
+ List<Map<String, List<SecondRiskControlRecord>>> groupedByRuleAndBusiness =
|
|
|
+ (List<Map<String, List<SecondRiskControlRecord>>>) riskControlRecords.stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ SecondRiskControlRecord::getRuleType,
|
|
|
+ Collectors.groupingBy(SecondRiskControlRecord::getBusinessId)
|
|
|
+ )).values();
|
|
|
+
|
|
|
+ for (Map<String, List<SecondRiskControlRecord>> byRuleAndBusiness : groupedByRuleAndBusiness) {
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("二手商品风控记录审核任务执行异常", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("二手商品风控记录审核任务执行完成");
|
|
|
+ }
|
|
|
}
|