Browse Source

Merge remote-tracking branch 'origin/dev' into dev

lyx 2 tuần trước cách đây
mục cha
commit
ee5ad7656d

+ 5 - 1
alien-entity/src/main/java/shop/alien/entity/store/LifeUserDynamics.java

@@ -136,5 +136,9 @@ public class LifeUserDynamics {
 
     @ApiModelProperty(value = "AI审核结果查询id")
     @TableField("ai_task_id")
-    private Integer aiTaskId;
+    private String aiTaskId;
+
+    @ApiModelProperty(value = "审核失败原因")
+    @TableField("reason")
+    private String reason;
 }

+ 73 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreVerificationCode.java

@@ -0,0 +1,73 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 短信验证码记录
+ */
+@Data
+@TableName("store_verification_code")
+public class StoreVerificationCode extends Model<StoreVerificationCode> {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("主键id")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty("业务类型 (0:登录,1:修改密码,2:注册,3:修改手机号,4:注销店铺,5:注销账号,6:忘记密码)")
+    @TableField("business_type")
+    private Integer businessType;
+
+    @ApiModelProperty("手机号")
+    @TableField("phone")
+    private String phone;
+
+    @ApiModelProperty("端区分(0:用户,1:商家,2:律师端)")
+    @TableField("app_type")
+    private Integer appType;
+
+    @ApiModelProperty("验证码")
+    @TableField("code")
+    private String code;
+
+    @ApiModelProperty("创建时间")
+    @TableField("created_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty("更新时间")
+    @TableField("updated_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty("创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty("更新人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+
+    @ApiModelProperty("删除标志(0:正常,1:删除)")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+}
+

+ 13 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreVerificationCodeMapper.java

@@ -0,0 +1,13 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.StoreVerificationCode;
+
+/**
+ * 短信验证码 Mapper
+ */
+@Mapper
+public interface StoreVerificationCodeMapper extends BaseMapper<StoreVerificationCode> {
+}
+

+ 20 - 0
alien-entity/src/main/resources/mapper/StoreVerificationCodeMapper.xml

@@ -0,0 +1,20 @@
+<?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="shop.alien.mapper.StoreVerificationCodeMapper">
+
+    <resultMap id="BaseResultMap" type="shop.alien.entity.store.StoreVerificationCode">
+        <id column="id" property="id"/>
+        <result column="business_type" property="businessType"/>
+        <result column="phone" property="phone"/>
+        <result column="app_type" property="appType"/>
+        <result column="code" property="code"/>
+        <result column="created_time" property="createdTime"/>
+        <result column="updated_time" property="updatedTime"/>
+        <result column="created_user_id" property="createdUserId"/>
+        <result column="updated_user_id" property="updatedUserId"/>
+        <result column="delete_flag" property="deleteFlag"/>
+    </resultMap>
+
+</mapper>
+

+ 119 - 25
alien-job/src/main/java/shop/alien/job/store/AiTagJob.java

@@ -3,15 +3,13 @@ package shop.alien.job.store;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
 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.Value;
 import org.springframework.http.*;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.LinkedMultiValueMap;
@@ -25,8 +23,6 @@ import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 
-import static com.alipay.api.internal.util.AlipayUtils.getFileSuffix;
-
 /**
  * 调用AI标签数据服务类
  *
@@ -38,8 +34,6 @@ import static com.alipay.api.internal.util.AlipayUtils.getFileSuffix;
 @RequiredArgsConstructor
 public class AiTagJob {
 
-    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
     private final RestTemplate restTemplate;
 
     private final TagsMainMapper tagsMainMapper;
@@ -77,9 +71,12 @@ public class AiTagJob {
     private String saveTagUrl;
 
     // 第三方接口地址 内容合规检测接口
-    @Value("${third-party-content-check.base-url:http://192.168.2.250:9000/ai/auto-review/api/v1/content_compliance/check}")
+    @Value("${third-party-contentcheck.base-url}")
     private String contentComplianceUrl;
 
+    @Value("${third-party-getresult.base-url}")
+    private String getResultUrl;
+
     //用户名
     @Value("${third-party-user-name.base-url}")
     private String userName;
@@ -582,13 +579,14 @@ public class AiTagJob {
         List<LifeUserDynamics> lifeUserDynamics = lifeUserDynamicsMapper.selectList(new LambdaQueryWrapper<LifeUserDynamics>()
                 .eq(LifeUserDynamics::getCheckFlag, 0).eq(LifeUserDynamics::getDeleteFlag, 0));
 
+        // 只依赖数据库字段即可判定待审核的动态,避免重复提交
         // 常见图片后缀(可按需添加,如 .heic、.svg 等)
         HashSet<String> IMAGE_SUFFIXES = new HashSet<>(Arrays.asList(
-                ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".heic", ".svg", ".tiff"
+                "jpg", "jpeg", "png", "gif", "bmp", "webp", "heic", "svg", "tiff"
         ));
         // 常见视频后缀(可按需添加,如 .avi、.flv 等)
         HashSet<String> VIDEO_SUFFIXES = new HashSet<>(Arrays.asList(
-                ".mp4", ".mov", ".mkv", ".avi", ".flv", ".wmv", ".mpeg", ".mpg", ".webm"
+                "mp4", "mov", "mkv", "avi", "flv", "wmv", "mpeg", "mpg", "webm"
         ));
 
         for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
@@ -597,7 +595,7 @@ public class AiTagJob {
             List<String> imageList = new ArrayList<>();
             List<String> videoList = new ArrayList<>();
             // 按分隔符拆分路径数组(处理连续分隔符如 ",," 产生的空字符串)
-            String[] allPaths = imagePath.split(imagePath);
+            String[] allPaths = imagePath.split(",");
             for (String path : allPaths) {
                 // 去除路径前后空格(避免 " a.jpg " 这类情况)
                 String trimmedPath = path.trim();
@@ -615,6 +613,7 @@ public class AiTagJob {
                 } else if (VIDEO_SUFFIXES.contains(suffix)) {
                     videoList.add(trimmedPath);
                 }
+                // 对每一条动态逐条申请 token 并提交,避免批量失败导致重试逻辑复杂化
                 try {
                     log.info("登录Ai服务获取token..." + loginUrl);
                     MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
@@ -645,6 +644,7 @@ public class AiTagJob {
                             aiHeaders.set("Authorization", "Bearer " + accessToken);
 
                             Map<String, Object> jsonBody = new HashMap<>();
+                            // text/img/video 三种维度一起传入 AI,便于一次完成合规审查
                             jsonBody.put("text", lifeUserDynamic.getContext());
                             jsonBody.put("imgUrl", imageList);
                             jsonBody.put("video", videoList);
@@ -656,21 +656,27 @@ public class AiTagJob {
                                 if (response.getStatusCodeValue() != 200) {
                                     log.error("AI内容审核接口调用失败 http状态:" + response.getStatusCode());
                                 }
-                                JsonNode responseNode = OBJECT_MAPPER.readTree(response.getBody());
-                                int code = responseNode.has("code") ? responseNode.get("code").asInt() : 0;
-                                if (code != 200) {
-                                    throw new RuntimeException("AI接口调用失败" + code);
+                                JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                                if (responseNode == null) {
+                                    log.error("AI接口调用失败,响应内容为空");
                                 }
-                                JsonNode dataNode = responseNode.get("data");
-
-                                if (dataNode.has("is_compliant")) {
-                                    LifeUserDynamics dynamics = new LifeUserDynamics();
-                                    dynamics.setId(lifeUserDynamic.getId());
-                                    dynamics.setCheckFlag(1);
-                                    lifeUserDynamicsMapper.updateById(dynamics);
+                                Integer code = null;
+                                if (responseNode != null) {
+                                    code = responseNode.getInteger("code");
+                                    if(code==200) {
+                                        JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                                        // 审核发起后仅标记 checkFlag=1 并保存任务号,等待回调或后续轮询更新
+                                        LifeUserDynamics dynamics = new LifeUserDynamics();
+                                        dynamics.setId(lifeUserDynamic.getId());
+                                        dynamics.setCheckFlag(1);
+                                        dynamics.setAiTaskId(dataNode.get("task_id").toString());
+                                        lifeUserDynamicsMapper.updateById(dynamics);
+                                        log.info("动态审核成功,AI返回内容: {}", response.getBody());
+                                        XxlJobHelper.handleSuccess("动态内容审核任务执行成功");
+                                    }
+                                }else {
+                                    log.error("AI接口调用失败,错误码: " + code);
                                 }
-                                log.info("动态审核成功,AI返回内容: {}", response.getBody());
-                                XxlJobHelper.handleSuccess("动态内容审核任务执行成功");
                             } catch (Exception e) {
                                 log.error("调用AI内容审核接口失败", e);
                             }
@@ -685,6 +691,95 @@ public class AiTagJob {
         return R.success("动态内容审核任务执行成功");
     }
 
+    /**
+     * 获取审核违规内容结果
+     */
+    @XxlJob("getCheckTask")
+    public R<String> getCheckTask() {
+        List<LifeUserDynamics> lifeUserDynamics = lifeUserDynamicsMapper.selectList(new LambdaQueryWrapper<LifeUserDynamics>()
+                .eq(LifeUserDynamics::getCheckFlag, 1).eq(LifeUserDynamics::getDeleteFlag, 0));
+
+        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+            // 针对已提交且未删除的动态轮询查询结果
+            try {
+                log.info("登录Ai服务获取token..." + loginUrl);
+                MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+                formData.add("username", userName);
+                formData.add("password", passWord);
+
+                HttpHeaders headers = new HttpHeaders();
+                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+                HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+                ResponseEntity<String> postForEntity = null;
+                try {
+                    log.info("请求Ai服务登录接口===================>");
+                    postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
+                } catch (Exception e) {
+                    log.error("请求AI服务登录接口失败", e);
+                }
+
+                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) {
+                        JSONObject dataJson = jsonObject.getJSONObject("data");
+                        String accessToken = dataJson.getString("access_token");
+
+                        // 创建带拦截器的RestTemplate
+                        // 使用拦截器统一追加 Authorization,避免每次手动设置 header
+                        RestTemplate restTemplateWithAuth = new RestTemplate();
+                        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
+                        interceptors.add((request, body, execution) -> {
+                            request.getHeaders().set("Authorization", "Bearer " + accessToken);
+                            return execution.execute(request, body);
+                        });
+                        restTemplateWithAuth.setInterceptors(interceptors);
+
+                        ResponseEntity<String> response = null;
+                        try {
+                            response = restTemplateWithAuth.getForEntity(getResultUrl + "?task_id="+lifeUserDynamic.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"));
+
+                                    if (!(boolean) dataNode.get("is_compliant")) {
+                                        // 只要 AI 判定不合规,立即禁用动态并记录原因
+                                        LifeUserDynamics dynamics = new LifeUserDynamics();
+                                        dynamics.setId(lifeUserDynamic.getId());
+                                        dynamics.setCheckFlag(2);
+                                        dynamics.setEnableStatus(1);
+                                        dynamics.setReason(String.valueOf(dataNode.get("failure_reason")));
+                                        lifeUserDynamicsMapper.updateById(dynamics);
+                                    }
+                                    log.info("动态审核结果获取成功,AI返回内容: {}", response.getBody());
+                                    XxlJobHelper.handleSuccess("动态内容审核任务结果获取执行成功");
+                                } else {
+                                    log.error("AI接口调用失败,错误码: " + code);
+                                }
+                            }
+                        } catch (Exception e) {
+                            log.error("调用AI内容审核结果获取接口失败", e);
+                        }
+                    }
+                }
+            } catch (RuntimeException ex) {
+                XxlJobHelper.handleFail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+            }
+        }
+        return R.success("动态内容审核任务结果获取执行成功");
+    }
+
     class AnalysisRequest {
         private String start_time;
         private String end_time;
@@ -705,5 +800,4 @@ public class AiTagJob {
             this.end_time = end_time;
         }
     }
-
 }

+ 3 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerUserLogInServiceImpl.java

@@ -117,6 +117,8 @@ public class LawyerUserLogInServiceImpl extends ServiceImpl<LawyerUserMapper, La
             user.setOrderReceivingStatus(1);
             user.setPassType(2);
             user.setConsultationFee(Integer.parseInt(lawyerFee));
+            user.setNickName(user.getName() != null && !user.getName().isEmpty() ?
+                    user.getName().charAt(0) + "律师" : "律师");
             lawyerUserMapper.insert(user);
             List<Integer> problemScenarioIds = lawyerUserDto.getProblemScenarioIds();
             for (int i = 0; i < problemScenarioIds.size(); i++) {
@@ -167,6 +169,7 @@ public class LawyerUserLogInServiceImpl extends ServiceImpl<LawyerUserMapper, La
         LawyerUser lawyerUser = new LawyerUser();
         lawyerUser.setId(lawyerUserDto.getId());
         lawyerUser.setLastOnlineTime(new Date());
+        lawyerUser.setIsOnline(0);
         lawyerUserMapper.updateById(lawyerUser);
         baseRedisService.delete("lawyer_" + lawyerUserDto.getPhone());
         return R.success("退出成功");

+ 206 - 0
alien-store/src/main/java/shop/alien/store/controller/LifeUserDynamicsController.java

@@ -1,7 +1,9 @@
 package shop.alien.store.controller;
 
+import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.fasterxml.jackson.databind.JsonNode;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.google.common.collect.Lists;
@@ -9,12 +11,21 @@ import io.swagger.annotations.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.vo.LifePinglunVo;
 import shop.alien.entity.store.vo.LifeUserDynamicsVo;
+import shop.alien.mapper.LifeUserDynamicsMapper;
 import shop.alien.mapper.LifeUserExpertOrderMapper;
 import shop.alien.mapper.LifeUserExpertWorksMapper;
 import shop.alien.store.service.LifeUserDynamicsService;
@@ -40,6 +51,8 @@ public class LifeUserDynamicsController {
 
     private final LifeUserExpertOrderMapper lifeUserExpertOrderMapper;
 
+    private final LifeUserDynamicsMapper lifeUserDynamicsMapper;
+
 
     @Autowired
     private TextModerationUtil textModerationUtil;
@@ -333,4 +346,197 @@ public class LifeUserDynamicsController {
         }
         return R.success("操作成功");
     }
+
+    @GetMapping("/testAI")
+    public R testAI() {
+        List<LifeUserDynamics> lifeUserDynamics = lifeUserDynamicsMapper.selectList(new LambdaQueryWrapper<LifeUserDynamics>()
+                .eq(LifeUserDynamics::getCheckFlag, 0).eq(LifeUserDynamics::getDeleteFlag, 0));
+
+        // 常见图片后缀(可按需添加,如 .heic、.svg 等)
+        HashSet<String> IMAGE_SUFFIXES = new HashSet<>(Arrays.asList(
+                "jpg", "jpeg", "png", "gif", "bmp", "webp", "heic", "svg", "tiff"
+        ));
+        // 常见视频后缀(可按需添加,如 .avi、.flv 等)
+        HashSet<String> VIDEO_SUFFIXES = new HashSet<>(Arrays.asList(
+                "mp4", "mov", "mkv", "avi", "flv", "wmv", "mpeg", "mpg", "webm"
+        ));
+        RestTemplate restTemplate = new RestTemplate();
+
+        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+            String imagePath = lifeUserDynamic.getImagePath();
+
+            List<String> imageList = new ArrayList<>();
+            List<String> videoList = new ArrayList<>();
+            // 按分隔符拆分路径数组(处理连续分隔符如 ",," 产生的空字符串)
+            String[] allPaths = imagePath.split(",");
+            for (String path : allPaths) {
+                // 去除路径前后空格(避免 " a.jpg " 这类情况)
+                String trimmedPath = path.trim();
+                if (trimmedPath.isEmpty()) {
+                    continue; // 跳过空路径
+                }
+                // 获取文件后缀(忽略大小写)
+                // 找到最后一个 "." 的位置
+                int lastDotIndex = trimmedPath.lastIndexOf('.');
+                // 截取后缀(从 "." 后一位到结尾)
+                String suffix = trimmedPath.substring(lastDotIndex + 1);
+                // 分类添加到对应列表
+                if (IMAGE_SUFFIXES.contains(suffix)) {
+                    imageList.add(trimmedPath);
+                } else if (VIDEO_SUFFIXES.contains(suffix)) {
+                    videoList.add(trimmedPath);
+                }
+                try {
+                    log.info("登录Ai服务获取token..." + "http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login");
+                    MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+                    formData.add("username", "UdUser");
+                    formData.add("password", "123456");
+
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+                    HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+                    ResponseEntity<String> postForEntity = null;
+                    try {
+                        log.info("请求Ai服务登录接口===================>");
+                        postForEntity = restTemplate.postForEntity("http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login", requestEntity, String.class);
+                    } catch (Exception e) {
+                        log.error("请求AI服务登录接口失败", e);
+                    }
+
+                    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) {
+                            JSONObject dataJson = jsonObject.getJSONObject("data");
+                            String accessToken = dataJson.getString("access_token");
+
+                            HttpHeaders aiHeaders = new HttpHeaders();
+                            aiHeaders.setContentType(MediaType.APPLICATION_JSON);
+                            aiHeaders.set("Authorization", "Bearer " + accessToken);
+
+                            Map<String, Object> jsonBody = new HashMap<>();
+                            jsonBody.put("text", lifeUserDynamic.getContext());
+                            jsonBody.put("imgUrl", imageList);
+                            jsonBody.put("video", videoList);
+
+                            HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
+                            ResponseEntity<String> response = null;
+                            try {
+                                response = restTemplate.postForEntity("http://192.168.2.250:9000/ai/auto-review/api/v1/multimodal_audit_task/submit", request, 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"));
+                                        LifeUserDynamics dynamics = new LifeUserDynamics();
+                                        dynamics.setId(lifeUserDynamic.getId());
+                                        dynamics.setCheckFlag(1);
+                                        dynamics.setAiTaskId(dataNode.get("task_id").toString());
+                                        lifeUserDynamicsMapper.updateById(dynamics);
+                                        log.info("动态审核成功,AI返回内容: {}", response.getBody());
+                                    }
+                                }else {
+                                    log.error("AI接口调用失败,错误码: " + code);
+                                }
+                            } catch (Exception e) {
+                                log.error("调用AI内容审核接口失败", e);
+                            }
+                        }
+                    }
+                } catch (RuntimeException ex) {
+                    return R.fail("动态内容审核任务执行失败:" + ex.getMessage());
+                }
+            }
+        }
+        return R.success("动态内容审核任务执行成功");
+    }
+
+    @GetMapping("/testAIGet")
+    public R testAIGet() {
+        List<LifeUserDynamics> lifeUserDynamics = lifeUserDynamicsMapper.selectList(new LambdaQueryWrapper<LifeUserDynamics>()
+                .eq(LifeUserDynamics::getCheckFlag, 1).eq(LifeUserDynamics::getDeleteFlag, 0));
+        RestTemplate restTemplate = new RestTemplate();
+        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+            try {
+                MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+                formData.add("username", "UdUser");
+                formData.add("password", "123456");
+
+                HttpHeaders headers = new HttpHeaders();
+                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+                HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+                ResponseEntity<String> postForEntity = null;
+                try {
+                    log.info("请求Ai服务登录接口===================>");
+                    postForEntity = restTemplate.postForEntity("http://192.168.2.250:9000/ai/user-auth-core/api/v1/auth/login", requestEntity, String.class);
+                } catch (Exception e) {
+                    log.error("请求AI服务登录接口失败", e);
+                }
+
+                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) {
+                        JSONObject dataJson = jsonObject.getJSONObject("data");
+                        String accessToken = dataJson.getString("access_token");
+
+                        HttpHeaders aiHeaders = new HttpHeaders();
+                        aiHeaders.setContentType(MediaType.APPLICATION_JSON);
+                        aiHeaders.set("Authorization", "Bearer " + accessToken);
+
+                        Map<String, Object> jsonBody = new HashMap<>();
+                        jsonBody.put("task_id", lifeUserDynamic.getAiTaskId());
+
+                        HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
+                        ResponseEntity<String> response = null;
+                        try {
+                            response = restTemplate.getForEntity("http://192.168.2.250:9000/ai/auto-review/api/v1/multimodal_audit_task/getResult?task_id="+lifeUserDynamic.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"));
+
+                                    if (!(boolean) dataNode.get("is_compliant")) {
+                                        LifeUserDynamics dynamics = new LifeUserDynamics();
+                                        dynamics.setId(lifeUserDynamic.getId());
+                                        dynamics.setCheckFlag(2);
+                                        dynamics.setEnableStatus(1);
+                                        dynamics.setReason(String.valueOf(dataNode.get("failure_reason")));
+                                        lifeUserDynamicsMapper.updateById(dynamics);
+                                    }
+                                    log.info("动态审核结果获取成功,AI返回内容: {}", response.getBody());
+//                                    XxlJobHelper.handleSuccess("动态内容审核任务结果获取执行成功");
+                                } else {
+                                    log.error("AI接口调用失败,错误码: " + code);
+                                }
+                            }
+                        } catch (Exception e) {
+                            log.error("调用AI内容审核结果获取接口失败", e);
+                        }
+                    }
+                }
+            } catch (RuntimeException ex) {
+//                XxlJobHelper.handleFail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+            }
+        }
+        return R.success("动态内容审核任务结果获取执行成功");
+    }
 }

+ 85 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreVerificationCodeController.java

@@ -0,0 +1,85 @@
+package shop.alien.store.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiOperationSupport;
+import io.swagger.annotations.ApiSort;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.StoreVerificationCode;
+import shop.alien.store.service.StoreVerificationCodeService;
+
+/**
+ * 短信验证码 CRUD
+ */
+@Api(tags = {"二期-验证码管理"})
+@Slf4j
+@ApiSort(30)
+@CrossOrigin
+@RestController
+@RequestMapping("/storeVerificationCode")
+@RequiredArgsConstructor
+public class StoreVerificationCodeController {
+
+    private final StoreVerificationCodeService storeVerificationCodeService;
+
+    @ApiOperation("分页查询验证码记录")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "appType", value = "端区分(0:用户,1:商家,2:律师端)", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "businessType", value = "业务类型", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "pageSize", value = "每页数量", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/page")
+    public R<IPage<StoreVerificationCode>> page(@RequestParam(value = "phone", required = false) String phone,
+                                                @RequestParam(value = "appType", required = false) Integer appType,
+                                                @RequestParam(value = "businessType", required = false) Integer businessType,
+                                                @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
+                                                @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
+        log.info("StoreVerificationCodeController.page?phone={}&appType={}&businessType={}&pageNum={}&pageSize={}",
+                phone, appType, businessType, pageNum, pageSize);
+        return R.data(storeVerificationCodeService.pageList(phone, appType, businessType, pageNum, pageSize));
+    }
+
+    @ApiOperation("根据ID获取验证码记录")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParam(name = "id", value = "主键id", dataType = "Integer", paramType = "path", required = true)
+    @GetMapping("/{id}")
+    public R<StoreVerificationCode> detail(@PathVariable("id") Integer id) {
+        log.info("StoreVerificationCodeController.detail?id={}", id);
+        return R.data(storeVerificationCodeService.getById(id));
+    }
+
+    @ApiOperation("新增验证码记录")
+    @ApiOperationSupport(order = 3)
+    @PostMapping
+    public R<StoreVerificationCode> create(@RequestBody StoreVerificationCode request) {
+        log.info("StoreVerificationCodeController.create?request={}", request);
+        return R.data(storeVerificationCodeService.create(request));
+    }
+
+    @ApiOperation("更新验证码记录")
+    @ApiOperationSupport(order = 4)
+    @PutMapping
+    public R<StoreVerificationCode> update(@RequestBody StoreVerificationCode request) {
+        log.info("StoreVerificationCodeController.update?request={}", request);
+        return R.data(storeVerificationCodeService.updateRecord(request));
+    }
+
+    @ApiOperation("删除验证码记录")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParam(name = "id", value = "主键id", dataType = "Integer", paramType = "path", required = true)
+    @DeleteMapping("/{id}")
+    public R<Boolean> delete(@PathVariable("id") Integer id) {
+        log.info("StoreVerificationCodeController.delete?id={}", id);
+        return R.data(storeVerificationCodeService.removeRecord(id));
+    }
+}
+

+ 36 - 0
alien-store/src/main/java/shop/alien/store/service/StoreVerificationCodeService.java

@@ -0,0 +1,36 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.StoreVerificationCode;
+
+/**
+ * 短信验证码 service
+ */
+public interface StoreVerificationCodeService extends IService<StoreVerificationCode> {
+
+    /**
+     * 分页查询
+     */
+    IPage<StoreVerificationCode> pageList(String phone,
+                                          Integer appType,
+                                          Integer businessType,
+                                          Integer pageNum,
+                                          Integer pageSize);
+
+    /**
+     * 新增记录
+     */
+    StoreVerificationCode create(StoreVerificationCode request);
+
+    /**
+     * 更新记录
+     */
+    StoreVerificationCode updateRecord(StoreVerificationCode request);
+
+    /**
+     * 删除
+     */
+    boolean removeRecord(Integer id);
+}
+

+ 71 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreVerificationCodeServiceImpl.java

@@ -0,0 +1,71 @@
+package shop.alien.store.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.store.StoreVerificationCode;
+import shop.alien.mapper.StoreVerificationCodeMapper;
+import shop.alien.store.service.StoreVerificationCodeService;
+
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * 短信验证码 service 实现
+ */
+@Service
+@RequiredArgsConstructor
+public class StoreVerificationCodeServiceImpl extends ServiceImpl<StoreVerificationCodeMapper, StoreVerificationCode>
+        implements StoreVerificationCodeService {
+
+    @Override
+    public IPage<StoreVerificationCode> pageList(String phone, Integer appType, Integer businessType, Integer pageNum, Integer pageSize) {
+        LambdaQueryWrapper<StoreVerificationCode> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StringUtils.isNotBlank(phone), StoreVerificationCode::getPhone, phone);
+        wrapper.eq(null != appType, StoreVerificationCode::getAppType, appType);
+        wrapper.eq(null != businessType, StoreVerificationCode::getBusinessType, businessType);
+        wrapper.eq(StoreVerificationCode::getDeleteFlag, 0);
+        wrapper.orderByDesc(StoreVerificationCode::getCreatedTime);
+        Page<StoreVerificationCode> page = new Page<>(null == pageNum ? 1 : pageNum, null == pageSize ? 10 : pageSize);
+        return this.page(page, wrapper);
+    }
+
+    @Override
+    public StoreVerificationCode create(StoreVerificationCode request) {
+        request.setId(null);
+        Date now = new Date();
+        request.setCreatedTime(now);
+        request.setUpdatedTime(now);
+        request.setDeleteFlag(0);
+        this.save(request);
+        return request;
+    }
+
+    @Override
+    public StoreVerificationCode updateRecord(StoreVerificationCode request) {
+        if (Objects.isNull(request.getId())) {
+            throw new IllegalArgumentException("id不能为空");
+        }
+        request.setUpdatedTime(new Date());
+        this.updateById(request);
+        return this.getById(request.getId());
+    }
+
+    @Override
+    public boolean removeRecord(Integer id) {
+        if (Objects.isNull(id)) {
+            return false;
+        }
+        StoreVerificationCode entity = new StoreVerificationCode();
+        entity.setId(id);
+        entity.setDeleteFlag(1);
+        entity.setUpdatedTime(new Date());
+        return this.updateById(entity);
+    }
+
+}
+