图片文字识别

This commit is contained in:
dzc committed 2025-11-07 17:40:02 +08:00
1 parent 89e8e40ddf
commit 29e3b787b0
6 files changed
+143 -30

No files matched your search

+22
View File
@@ -141,4 +141,26 @@ CREATE TABLE `member_location`
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 32 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户位置记录';
-- ----------------------------
-- Table structure for member_location
-- ----------------------------
DROP TABLE IF EXISTS `member_location`;
CREATE TABLE `member_location`
(
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '会员id',
`long` double precision DEFAULT NULL COMMENT '经度',
`lat` double precision DEFAULT NULL COMMENT '纬度',
`province` varchar(64) DEFAULT NULL COMMENT '省',
`city` varchar(64) DEFAULT NULL COMMENT '市',
`district` varchar(64) DEFAULT NULL COMMENT '区',
`address` varchar(256) DEFAULT NULL COMMENT '详细地址',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
`tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 32 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户位置记录';
@@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.member.api.thirdauth;
import lombok.Data;
@Data
public class ThirdAuthVo {
private Boolean isSuccess = true;
private String firstErrorMsg;
private String errorMsg;
public boolean isError(){
return !isSuccess;
}
}
@@ -89,7 +89,7 @@
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>green20220302</artifactId>
<version>2.21.1</version>
<version>3.0.1</version>
</dependency>
</dependencies>
@@ -5,6 +5,7 @@ import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.member.api.thirdauth.ThirdAuthVo;
import cn.iocoder.yudao.module.member.controller.app.recent.vo.AppRecentLikeReqVo;
import cn.iocoder.yudao.module.member.controller.app.recent.vo.AppRecentOperateReqVo;
import cn.iocoder.yudao.module.member.dal.dataobject.location.LocationDO;
@@ -16,8 +17,6 @@ import cn.iocoder.yudao.module.member.enums.MemberRecentOperateEnum;
import cn.iocoder.yudao.module.member.service.location.LocationService;
import cn.iocoder.yudao.module.member.service.thirdauth.ThirdAuthService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import com.aliyun.green20220302.models.ImageBatchModerationResponseBody;
import com.aliyun.green20220302.models.TextModerationPlusResponseBody;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -81,20 +80,26 @@ public class RecentServiceImpl implements RecentService {
recentMapper.insert(recent);
// 文字和图片违规处理
CompletableFuture<TextModerationPlusResponseBody.TextModerationPlusResponseBodyData> textFuture = CompletableFuture.supplyAsync(() -> thirdAuthService.textAuditSync(vo.getDescription()));
CompletableFuture<ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyData> imageFuture = CompletableFuture.supplyAsync(() -> thirdAuthService.imageAuditSync(vo.getCoverPic()));
CompletableFuture<ThirdAuthVo> textFuture = CompletableFuture.supplyAsync(() -> thirdAuthService.textAuditSync(vo.getDescription()));
CompletableFuture<ThirdAuthVo> imageFuture = CompletableFuture.supplyAsync(() -> thirdAuthService.imageAuditSync(vo.getCoverPic()));
try {
TextModerationPlusResponseBody.TextModerationPlusResponseBodyData textRes = textFuture.get();
ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyData imageRes = imageFuture.get();
ThirdAuthVo textRes = textFuture.get();
ThirdAuthVo imageRes = imageFuture.get();
// 处理文字
if (ObjectUtil.isEmpty(textRes)) {
throw exception(MemberErrorCode.CHECK_TEXT_NOT_PASS, "未知错误");
}
if (textRes.isError() && ObjectUtil.isNotEmpty(textRes.getFirstErrorMsg())) {
throw exception(MemberErrorCode.CHECK_TEXT_NOT_PASS, textRes.getFirstErrorMsg());
}
// 处理图片
if (ObjectUtil.isEmpty(imageRes)) {
throw exception(MemberErrorCode.CHECK_IMAGE_NOT_PASS, "未知错误");
}
if (imageRes.isError() && ObjectUtil.isNotEmpty(imageRes.getFirstErrorMsg())) {
throw exception(MemberErrorCode.CHECK_TEXT_NOT_PASS, imageRes.getFirstErrorMsg());
}
} catch (Exception e) {
log.error("|创建朋友圈|,以外的错误error:{}", e.getMessage());
throw new RuntimeException(e.getMessage());
@@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.member.service.thirdauth;
import cn.iocoder.yudao.module.member.api.thirdauth.ThirdAuthVo;
import com.aliyun.green20220302.models.ImageBatchModerationResponseBody;
import com.aliyun.green20220302.models.TextModerationPlusResponseBody;
/**
* @author liusiyang_dxm
@@ -12,11 +12,11 @@ public interface ThirdAuthService {
/**
* 文本审核
*/
TextModerationPlusResponseBody.TextModerationPlusResponseBodyData textAuditSync(String text);
ThirdAuthVo textAuditSync(String text);
/**
* 图片审核-同步
*/
ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyData imageAuditSync(String imageUrl);
ThirdAuthVo imageAuditSync(String imageUrl);
}
@@ -1,9 +1,14 @@
package cn.iocoder.yudao.module.member.service.thirdauth;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.member.api.thirdauth.ThirdAuthVo;
import com.alibaba.fastjson.JSON;
import com.aliyun.green20220302.Client;
import com.aliyun.green20220302.models.*;
import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyData;
import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyDataResult;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
@@ -11,9 +16,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.*;
/**
* 第三方审核
@@ -25,6 +28,11 @@ public class ThirdAuthServiceImpl implements ThirdAuthService {
private volatile Client clientInstance;
private final List<String> successRiskLevelList = new ArrayList<String>() {{
add("low");
add("none");
}};
/**
* 初始化第三方审核
*/
@@ -38,9 +46,9 @@ public class ThirdAuthServiceImpl implements ThirdAuthService {
config.setAccessKeySecret("EVXWFTS2SB6UkjUVFLhTDBfIvIXgI3");
config.setEndpoint("green-cip.cn-shanghai.aliyuncs.com");
//读取时超时时间,单位毫秒(ms)
config.setReadTimeout(6000);
config.setReadTimeout(10_000);
//连接时超时时间,单位毫秒(ms)
config.setConnectTimeout(3000);
config.setConnectTimeout(10_000);
clientInstance = new Client(config);
} catch (Exception e) {
e.printStackTrace();
@@ -56,11 +64,13 @@ public class ThirdAuthServiceImpl implements ThirdAuthService {
* 文本审核
*/
@Override
public TextModerationPlusResponseBody.TextModerationPlusResponseBodyData textAuditSync(String text) {
public ThirdAuthVo textAuditSync(String text) {
ThirdAuthVo resultVo = new ThirdAuthVo();
try {
Client client = createClient();
if (ObjectUtil.isEmpty(client)) return null;
HashMap<String, Object> query = new HashMap<>();
query.put("content", text);
TextModerationPlusRequest textModerationPlusRequest = new TextModerationPlusRequest();
// 检测类型
textModerationPlusRequest.setService("comment_detection_pro");
@@ -69,12 +79,56 @@ public class ThirdAuthServiceImpl implements ThirdAuthService {
if (response.getStatusCode() != 200) {
throw new RuntimeException("文本审核失败code:" + response.getStatusCode());
}
TextModerationPlusResponseBody result = response.getBody();
return result.getData();
TextModerationPlusResponseBody body = response.getBody();
if (ObjectUtil.isEmpty(body)) {
throw new RuntimeException("body为null");
}
TextModerationPlusResponseBody.TextModerationPlusResponseBodyData data = body.getData();
if (ObjectUtil.isEmpty(data)) {
throw new RuntimeException("data为null");
}
/*
high:高风险(若命中自定义词库,风险等级默认为高风险)
medium:中风险
low:低风险
none:无风险
*/
if (successRiskLevelList.contains(data.getRiskLevel())) {
resultVo.setIsSuccess(true);
return resultVo;
}
List<TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult> list = data.getResult();
if (ObjectUtil.isEmpty(list)) {
throw new RuntimeException("result为null");
}
StringBuilder errorMsg = new StringBuilder();
String firstErrorMsg = "你发送的内容";
for (TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult v : list) {
// 检测结果
String description = v.getDescription();
// 置信分值
Float confidence = v.getConfidence();
// 有问题的词汇
String riskWords = v.getRiskWords();
if (confidence >= 80) {
errorMsg.append(String.format("[%s]疑似%s,", riskWords, description));
}
}
if (ObjectUtil.isNotEmpty(errorMsg)) errorMsg.append("请重新编辑");
// confidence最大的数据
TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult max = list.stream().max((pren, next) -> next.getConfidence().compareTo(pren.getConfidence())).orElse(null);
if (ObjectUtil.isNotEmpty(max)) {
firstErrorMsg = String.format("你发送的内容[%s]疑似%s,请重新编辑", max.getRiskWords(), max.getDescription());
}
resultVo.setIsSuccess(false);
resultVo.setErrorMsg(errorMsg.toString());
resultVo.setFirstErrorMsg(firstErrorMsg);
return resultVo;
} catch (Exception e) {
e.printStackTrace();
log.error("|文本审核|,意外的错误text:{}error:{}", text, e.getMessage());
return null;
resultVo.setIsSuccess(true);
return resultVo;
}
}
@@ -82,27 +136,41 @@ public class ThirdAuthServiceImpl implements ThirdAuthService {
* 图片审核-同步
*/
@Override
public ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyData imageAuditSync(String imageUrl) {
public ThirdAuthVo imageAuditSync(String imageUrl) {
ThirdAuthVo resultVo = new ThirdAuthVo();
try {
Client client = createClient();
if (ObjectUtil.isEmpty(client)) return null;
RuntimeOptions runtime = new RuntimeOptions();
Map<String, String> query = new HashMap<>();
query.put("imageUrl", imageUrl);
query.put("dataId", UUID.randomUUID().toString());
ImageBatchModerationRequest imageBatchModerationRequest = new ImageBatchModerationRequest();
imageBatchModerationRequest.setService("baselineCheck,baselineCheck_pro");
imageBatchModerationRequest.setServiceParameters(JSONUtil.toJsonStr(query));
ImageBatchModerationResponse response = client.imageBatchModerationWithOptions(imageBatchModerationRequest, runtime);
Map<String, String> serviceParameters = new HashMap<>();
serviceParameters.put("imageUrl", "https://img.alicdn.com/tfs/TB1U4r9AeH2gK0jSZJnXXaT1FXa-2880-480.png");
serviceParameters.put("dataId", String.valueOf(UUID.randomUUID()));
serviceParameters.put("infoType", "customImage,textInImage,publicFigure");
ImageModerationRequest imageBatchModerationRequest = new ImageModerationRequest();
imageBatchModerationRequest.setService("baselineCheck");
imageBatchModerationRequest.setServiceParameters(JSON.toJSONString(serviceParameters));
ImageModerationResponse response = client.imageModerationWithOptions(imageBatchModerationRequest, runtime);
if (response.getStatusCode() != 200) {
throw new RuntimeException("文本审核失败code:" + response.getStatusCode());
}
ImageBatchModerationResponseBody result = response.getBody();
return result.getData();
ImageModerationResponseBody body = response.getBody();
if (ObjectUtil.isEmpty(body)) {
throw new RuntimeException("body为null");
}
ImageModerationResponseBody.ImageModerationResponseBodyData data = body.getData();
if (ObjectUtil.isEmpty(data)) {
throw new RuntimeException("data为null");
}
List<ImageModerationResponseBody.ImageModerationResponseBodyDataResult> list = data.getResult();
if (ObjectUtil.isEmpty(list)) {
throw new RuntimeException("result为null");
}
return resultVo;
} catch (Exception e) {
e.printStackTrace();
log.error("|图片审核-同步|,意外的错误text:{}error:{}", imageUrl, e.getMessage());
return null;
resultVo.setIsSuccess(true);
return resultVo;
}
}