Browse Source

灵州0.45B模型调用+绍兴智能体调用测试

master
wangxun 3 days ago
parent
commit
55255e902b
6 changed files with 499 additions and 15 deletions
  1. +45
    -1
      src/main/java/com/inspect/simulator/controller/ModelController.java
  2. +2
    -0
      src/main/java/com/inspect/simulator/domain/visual/VisualJson.java
  3. +20
    -5
      src/main/java/com/inspect/simulator/service/ModelService.java
  4. +3
    -1
      src/main/java/com/inspect/simulator/service/impl/LuminosityRequestConsumerManager.java
  5. +426
    -6
      src/main/java/com/inspect/simulator/service/impl/ModelServiceImpl.java
  6. +3
    -2
      src/main/resources/mapper/ResultAnalysisMapper.xml

+ 45
- 1
src/main/java/com/inspect/simulator/controller/ModelController.java View File

@ -1,15 +1,20 @@
package com.inspect.simulator.controller;
import com.inspect.simulator.domain.visual.ApiVisualRequest;
import com.inspect.simulator.domain.visual.ImageData;
import com.inspect.simulator.hikVision.utils.AjaxResult;
import com.inspect.simulator.service.ModelService;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import sun.rmi.runtime.Log;
import javax.annotation.Resource;
@RestController
@CrossOrigin
@Slf4j
public class ModelController {
@Resource
private ModelService modelService;
@ -32,7 +37,7 @@ public class ModelController {
}
//视觉大模型
//1.9视觉大模型
@PostMapping("/model/visualization")
@ResponseBody
public AjaxResult Visualization(@RequestBody String analyseRequestStr)
@ -41,4 +46,43 @@ public class ModelController {
return AjaxResult.success().put("data", i);
}
//0.45B视觉大模型
@PostMapping("/model/visualizationFf")
@ResponseBody
public AjaxResult VisualizationFf(@RequestBody String analyseRequestStr)
{
final int i = modelService.protractImgVisualizationFf(analyseRequestStr);
return AjaxResult.success().put("data", i);
}
//--------
//绍兴-智能体-获取会话sesssionId
@PostMapping("/model/getSessionId")
@ResponseBody
public String createSession()
{
String sessionId = null;
try {
sessionId = modelService.createSession();
} catch (Exception e) {
throw new RuntimeException(e);
}
return sessionId;
}
@PostMapping("/model/getAnswer")
@ResponseBody
public String getAnswer(@RequestParam String imgUrl)
{
log.info("路径:{}",imgUrl);
String answer = modelService.sessionAnswer(imgUrl);
return answer;
}
}

+ 2
- 0
src/main/java/com/inspect/simulator/domain/visual/VisualJson.java View File

@ -26,4 +26,6 @@ public class VisualJson {
private String useType;//传参算法类型
private String imgUrl;
private String description;//描述
}

+ 20
- 5
src/main/java/com/inspect/simulator/service/ModelService.java View File

@ -1,13 +1,9 @@
package com.inspect.simulator.service;
import com.inspect.simulator.domain.assistant.Session;
import com.inspect.simulator.domain.bigmodelr.Multimodal;
import com.inspect.simulator.domain.bigmodelr.VisualModel;
import com.inspect.simulator.domain.visual.ImageData;
import java.util.List;
public interface ModelService {
//语义大模型
@ -20,9 +16,28 @@ public interface ModelService {
int bigModelPicAnalyse(String analyseRequestStr);
//视觉大模型服务接口
//视觉大模型服务接口1.9
String Visualization(ImageData imageData);
//1.9B视觉大模型
int protractImgVisualization(String analyseRequestStr);
//0.45B视觉大模型服务接口-不规范弃用
// String VisualizationBase64(ApiVisualRequest visualRequest);
//0.45B视觉大模型服务接口
String Visualization_045b(ImageData imageData);
//0.45B视觉大模型服务接口-规范调用
int protractImgVisualizationFf(String analyseRequestStr);
//绍兴智能体sessionId-获取
String createSession() throws Exception;
//绍兴智能体会话问答
String sessionAnswer(String imgUrl);
//绍兴智能体--规范返回
int agentInquiry(String analyseRequestStr);
}

+ 3
- 1
src/main/java/com/inspect/simulator/service/impl/LuminosityRequestConsumerManager.java View File

@ -49,7 +49,9 @@ public class LuminosityRequestConsumerManager {
//多模态大模型
// modelService.bigModelPicAnalyse(requestInfo);
//视觉大模型1.9B
modelService.protractImgVisualization(requestInfo);
// modelService.protractImgVisualization(requestInfo);
//绍兴-智能体
modelService.agentInquiry(requestInfo);
}
} catch (Exception e) {
log.info("LuminosityRequestConsumerManager error queueSize: {}, request: {}", getQueueSize(), request);


+ 426
- 6
src/main/java/com/inspect/simulator/service/impl/ModelServiceImpl.java View File

@ -3,6 +3,7 @@ package com.inspect.simulator.service.impl;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.inspect.simulator.domain.algorithm.in.AnalyseRequest;
@ -32,7 +33,9 @@ import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -58,8 +61,8 @@ public class ModelServiceImpl implements ModelService {
private String hrFtpUrl = "ftp://ftpuser:atia2018@192.168.4.129:10012/";
// @Value("${file.ftpUrlAddress:test}")
private String ftpUrlAddress = "192.168.4.129";
// private String ftpUrlAddress = "192.168.1.116";
// private String ftpUrlAddress = "192.168.4.129";
private String ftpUrlAddress = "192.168.1.116";
// @Value("${file.ftpUrlAccount:test}")
private String ftpUrlAccount = "ftpuser";
@ -68,8 +71,8 @@ public class ModelServiceImpl implements ModelService {
private String ftpUrlPwd = "atia2018";
// @Value("${file.ftpUrlPort:10000}")
private Integer ftpUrlPort = 10012;
// private Integer ftpUrlPort = 10990;
// private Integer ftpUrlPort = 10012;
private Integer ftpUrlPort = 10990;
@Resource
private AnalysisRemoteService analysisRemoteService;
@ -464,6 +467,25 @@ public class ModelServiceImpl implements ModelService {
}
}
//inputStream转base64
public String downloadAndConvertToBase64(InputStream inputStream) {
try ( ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
byte[] data = new byte[4096];
int nRead;
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
return Base64.getEncoder().encodeToString(buffer.toByteArray());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private ChatCompletionResponse sendRequest(ChatCompletionRequest request) throws IOException {
log.info("多模态搭模型请求路径信息:路径" + dmtModelUrl + ",请求头key: " + dmtModelHeader);
@ -496,7 +518,7 @@ public class ModelServiceImpl implements ModelService {
}
//设置规范调用视觉大模型
//设置规范调用1.9b视觉大模型
public int protractImgVisualization(String analyseRequestStr) {
int j=-1;
String visualization = null;
@ -702,7 +724,7 @@ public class ModelServiceImpl implements ModelService {
return inputStream;
}
//视觉大模型
//1.9B视觉大模型
@Override
public String Visualization(ImageData imageData) {
@ -752,4 +774,402 @@ public class ModelServiceImpl implements ModelService {
return responseJson;
}
// @Override
// public String VisualizationBase64(ApiVisualRequest request) {
// String responseJson = null;
// ObjectMapper objectMapper = new ObjectMapper();
// try {
// // 1. 处理图像数据
// String imagePath = request.getData().getImage_data();
// String base64String = convertToBase64(imagePath);
// if (base64String == null) {
// throw new RuntimeException("图片Base64转换失败: " + imagePath);
// }
// // 2. 构建请求体根据实际需求选择数组或对象格式
// Map<String, Object> requestBody = new HashMap<>();
// requestBody.put("model", request.getModel());
//
// List<Map<String, String>> dataList = new ArrayList<>();
// Map<String, String> imageData = new HashMap<>();
// imageData.put("image_name", request.getData().getImage_name());
// imageData.put("image_type", "base64");
// imageData.put("image_data", "data:image/jpg;base64," + base64String);
// dataList.add(imageData);
// requestBody.put("data", dataList);
//
// // 3. 构建HTTP请求
// String requestBodyJson = objectMapper.writeValueAsString(requestBody);
// log.debug("请求体内容: {}", requestBodyJson);
//
// Request httpRequest = new Request.Builder()
// .url("http://25.80.45.92:18063/imageTechnology/lswcv/detect")
// .post(RequestBody.create(MediaType.parse("application/json"), requestBodyJson))
// .addHeader("Content-Type", "application/json")
// .build();
//
// // 4. 执行请求并处理响应
// try (Response response = httpClient.newCall(httpRequest).execute()) {
// if (!response.isSuccessful()) {
// String errorBody = response.body() != null ? response.body().string() : "无响应体";
// throw new IOException("API请求失败: " + response.code() + ", " + errorBody);
// }
//
// responseJson = response.body().string();
// log.info("API响应: {}", responseJson);
// }
// } catch (Exception e) {
// log.error("处理0.45B视觉请求时发生异常", e);
// throw new RuntimeException("0.45B视觉处理服务异常: " + e.getMessage(), e);
// }
// return responseJson;
// }
//设置规范调用0.45Bb视觉大模型
public int protractImgVisualizationFf(String analyseRequestStr) {
int j=-1;
String visualization = null;
ApiVisualResponse apiVisualResponse = new ApiVisualResponse();
log.info(Color.MAGENTA + "[ Visualization] bigModelPicAnalyse: analyseRequestStr={}", analyseRequestStr);
AnalyseRequest analyseRequest = new Gson().fromJson(analyseRequestStr, AnalyseRequest.class);
String imgUrl = analyseRequest.getObjectList().get(0).getImageUrlList()[0];
String lineId = patrolResultMapper.selectPatrolResultByTaskPatrolledId(analyseRequest.getTaskPatrolId(), analyseRequest.getObjectList().get(0).getObjectId());
String[] typeList = analyseRequest.getObjectList().get(0).getTypeList();
List<VisualJson> visualJsonList = new ArrayList<>();
String imageName = imgUrl.substring(imgUrl.lastIndexOf("/") + 1);//图片名称
Path path = Paths.get(imgUrl);
String directoryPath = path.getParent().toString().replace("\\", "/") + "/"; // 获取图片所在目录并统一使用正斜杠
// 新文件路径
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
String markPicName = sf.format(date);
String pureName = imageName.substring(0, imageName.lastIndexOf('.'));
String outputPath = directoryPath + pureName + "_" + markPicName + ".jpg";
ImageData imageData = new ImageData();
imageData.setImage_name(imageName);
imageData.setImage_data(analyseRequest.getObjectList().get(0).getImageUrlList()[0]);
//下载图片
InputStream inputStream = downloadFtp(imgUrl);
//调用视觉大模型
visualization = this.Visualization_045b(imageData);
if (StringUtils.isNotEmpty(visualization)) {
try {
apiVisualResponse = objectMapper.readValue(visualization, ApiVisualResponse.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
} else {
log.info(imageName + "图片,0.45b视觉大模型无返回,使用默认数据");
// visualization = "{\"traceId\":\"88e754a8-1d07-4bbd-9d43-98ac40bdb7ad\",\"success\":true,\"data\":[{\"error_code\":0,\"image_name\":\"1613_20250711173000_2081817_02160558348850500131.jpg\",\"image_height\":720,\"image_width\":1280,\"infer_results\":[{\"bbox\":[533.7729,583.49506,773.02124,718.8728],\"category\":\"箱门闭合异常-箱门闭合正常\",\"score\":0.96470034},{\"bbox\":[795.3903,536.1146,1043.0077,718.15497],\"category\":\"箱门闭合异常-箱门闭合正常\",\"score\":0.9343145},{\"bbox\":[1057.7261,638.2431,1223.5446,719.07074],\"category\":\"箱门闭合异常-箱门闭合正常\",\"score\":0.8148986},{\"bbox\":[318.5776,0.34692764,566.56915,592.8563],\"category\":\"设备积污-表面污秽\",\"score\":0.064688765}]}],\"timeUsed\":411}\n";
visualization="{\"data\":[{\"image_height\":720,\"image_name\":\"21.jpg\",\"image_width\":1280,\"infer_results\":[{\"bbox\":[4,230,944,715],\"category\":\"\\u57fa\\u7840\\u7c7b-\\u7acb\\u67f1\\u6df9\\u6ca1\",\"score\":0.74},{\"bbox\":[0,224,962,721],\"category\":\"\\u6e17\\u6f0f\\u6cb9-\\u5730\\u9762\\u6cb9\\u6c61\",\"score\":0.88}]}],\"success\":true,\"traceId\":\"0c9aabf5-4b6f-413c-b5f1-6636b071368a\"}";
try {
apiVisualResponse = objectMapper.readValue(visualization, ApiVisualResponse.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
InputStream outputImageStream = null;
try {
outputImageStream = drawBoundingBoxesAndSave(apiVisualResponse, inputStream);
} catch (IOException e) {
e.printStackTrace();
}
if (outputImageStream != null) {
log.info("视觉大模型复筛图片" + imageName + "已上传到:" + outputPath);
this.picFtp(outputPath, outputImageStream, ftpUrlAddress, ftpUrlPort, ftpUrlAccount, ftpUrlPwd);
for (int i = 0; i < typeList.length; i++) {
VisualJson visualJson =new VisualJson();
//存入数据库
String objectId = analyseRequest.getObjectList().get(0).getObjectId();
visualJson.setDefectType(apiVisualResponse.getData().get(0).getInfer_results().get(0).getCategory());
visualJson.setObjectId(objectId);
visualJson.setFilter("2");
visualJson.setTaskPatrolId(analyseRequest.getTaskPatrolId());
visualJson.setBusinessId(lineId);
visualJson.setImgUrl(outputPath);
visualJson.setUseType(typeList[i]);
visualJsonList.add(visualJson);
}
j = resultAnalysisMapper.addVisualModelInfo(visualJsonList);
}
return j;
}
//0.45B视觉请求调用
@Override
public String Visualization_045b(ImageData data) {
String responseJson = null;
ObjectMapper objectMapper = new ObjectMapper();
try {
// 1. 处理图像数据
// String base64String = convertToBase64(imagePath);
//连接ftp下载图片转BASE64
InputStream inputStream = downloadFtp(data.getImage_data());
String base64String = downloadAndConvertToBase64(inputStream);
if (base64String == null) {
throw new RuntimeException("图片Base64转换失败: " + data.getImage_data());
}
Path path = Paths.get(data.getImage_data());
String imgName = path.getFileName().toString();// 直接获取带后缀的文件名
// 2. 构建请求体根据curl示例格式
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", "eprim");
List<Map<String, String>> dataList = new ArrayList<>();
Map<String, String> imageData = new HashMap<>();
imageData.put("image_name", imgName);
imageData.put("image_type", "base64");
imageData.put("image_data", "data:image/jpeg;base64," + base64String);
dataList.add(imageData);
requestBody.put("data", dataList);
// 3. 构建HTTP请求
String requestBodyJson = objectMapper.writeValueAsString(requestBody);
log.debug("请求体内容: {}", requestBodyJson);
Request httpRequest = new Request.Builder()
.url("http://25.80.45.92:18063/imageTechnology/cvlsw/api") // 更新URL
.post(RequestBody.create(MediaType.parse("application/json"), requestBodyJson))
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "*/*")
.addHeader("Accept-Encoding", "gzip, deflate")
.addHeader("Cache-Control", "no-cache")
.addHeader("Connection", "keep-alive")
.addHeader("Host", "25.80.45.92:18063")
.addHeader("User-Agent", "PostmanRuntime/7.18.0")
.addHeader("cache-control", "no-cache")
.build();
// 4. 执行请求并处理响应
try (Response response = httpClient.newCall(httpRequest).execute()) {
if (!response.isSuccessful()) {
String errorBody = response.body() != null ? response.body().string() : "无响应体";
throw new IOException("API请求失败: " + response.code() + ", " + errorBody);
}
responseJson = response.body().string();
log.info("API响应: {}", responseJson);
}
} catch (Exception e) {
log.error("处理0.45B视觉请求时发生异常", e);
return null;
}
return responseJson;
}
//绍兴智能体
//绍兴智能体 sessionId-获取
public String createSession() throws Exception {
// 请求URL
URL url = new URL("http://25.90.210.236/lmp-cloud-ias-server/api/session/create");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
// 设置请求参数
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", "1c01eb546de442a09a16db21c564802c");
connection.setDoOutput(true);
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
// 请求体
String requestBody = "{\"agentId\":\"1fd10e55-0a30-447d-95a8-a0de5423ab57\",\"agentVersion\":\"1754557192722\"}";
// 发送请求体
try (OutputStream os = connection.getOutputStream()) {
byte[] input = requestBody.getBytes("utf-8");
os.write(input, 0, input.length);
}
// 获取响应
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
// 解析sessionId简单字符串处理
String responseBody = response.toString();
if (responseBody.contains("\"sessionId\"")) {
String sessionId = responseBody.split("\"sessionId\":\"")[1].split("\"")[0];
return sessionId;
} else {
throw new RuntimeException("获取sessionId失败: " + responseBody);
}
}
} else {
throw new RuntimeException("HTTP请求失败,状态码: " + responseCode);
}
} finally {
connection.disconnect();
}
}
// 运行会话
public String runSession(String sessionId, String query, String imageBase64) throws Exception {
String textContent = String.format(
"{\"model\":\"rsv-sh58jisx\",\"query\":\"%s\",\"imagebase\":\"%s\"}",
escapeJsonString(query),
imageBase64 != null ? imageBase64 : ""
);
String requestBody = String.format(
"{\"agentId\":\"1fd10e55-0a30-447d-95a8-a0de5423ab57\",\"agentVersion\":\"1754557192722\",\"sessionId\":\"%s\",\"stream\":false,\"text\":\"%s\"}",
sessionId,
escapeJsonString(textContent)
);
URL url = new URL("http://25.90.210.236/lmp-cloud-ias-server/api/session/run");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", "1c01eb546de442a09a16db21c564802c");
connection.setDoOutput(true);
connection.setConnectTimeout(10000);
connection.setReadTimeout(30000);
try (OutputStream os = connection.getOutputStream()) {
byte[] input = requestBody.getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
return parseAnswer(response.toString());
}
} else {
throw new RuntimeException("运行会话失败,状态码: " + responseCode);
}
} finally {
connection.disconnect();
}
}
private String parseAnswer(String responseBody) {
if (responseBody.contains("\"answer\"")) {
String answer = responseBody.split("\"answer\":\"")[1].split("\"")[0];
return answer.replace("\\\"", "\"").replace("\\\\", "\\");
} else {
throw new RuntimeException("获取answer失败: " + responseBody);
}
}
//转义
private String escapeJsonString(String input) {
return input.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
public String sessionAnswer(String imgUrl) {
String answer="";
// 1. 创建会话
log.info("正在创建会话...");
String sessionId = null;
try {
sessionId = createSession();
log.info("会话创建成功,sessionId: " + sessionId);
// 2. 运行会话
log.info("正在向大模型提问...");
//String query = "#角色 你是电力缺陷识别专家,擅长识别并框选设备缺陷、环境异常等。#功能 根据我发送给你的图像,识别一下图像中的信息,给出缺陷或异常的描述。";
String query ="这张图片里有什么?";
// String base64String = convertToBase64(imgUrl);
// 转换图片为base64
InputStream inputStream = downloadFtp(imgUrl);
byte[] fileBytes = IOUtils.toByteArray(inputStream);
String base64String = Base64.getEncoder().encodeToString(fileBytes);
if (base64String != null) {
answer = runSession(sessionId, query, base64String);
log.info("大模型回答: " + answer);
} else {
log.info(imgUrl + "图片转base64未成功!");
}
return answer;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public int agentInquiry(String analyseRequestStr) {
String answer="";
ObjectMapper objectMapper = new ObjectMapper();
List<VisualJson> visualJsonList = new ArrayList<>();
log.info(Color.MAGENTA + "[Agent Inquiry ShaoXing] agentInquiry: analyseRequestStr={}", analyseRequestStr);
AnalyseRequest analyseRequest = new Gson().fromJson(analyseRequestStr, AnalyseRequest.class);
String imgUrl = analyseRequest.getObjectList().get(0).getImageUrlList()[0];
String lineId = patrolResultMapper.selectPatrolResultByTaskPatrolledId(analyseRequest.getTaskPatrolId(), analyseRequest.getObjectList().get(0).getObjectId());
//调用绍兴-智能体
String answerResult = this.sessionAnswer(imgUrl);
log.info("调用绍兴智能体响应结果:" + answerResult);
if (StringUtils.isNotEmpty(answerResult)){
JsonNode jsonNode = null;
try {
//获取answer-大模型回答
jsonNode = objectMapper.readTree(answerResult);
answer = jsonNode.get("data").get("answer").asText();
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
//返回结构体
String[] typeList = analyseRequest.getObjectList().get(0).getTypeList();
for (int i = 0; i < typeList.length; i++) {
VisualJson visualJson =new VisualJson();
//存入数据库
String objectId = analyseRequest.getObjectList().get(0).getObjectId();
visualJson.setObjectId(objectId);
visualJson.setFilter("2");
visualJson.setTaskPatrolId(analyseRequest.getTaskPatrolId());
visualJson.setBusinessId(lineId);
visualJson.setUseType(typeList[i]);
//answer
visualJson.setDescription(answer);
visualJsonList.add(visualJson);
}
return resultAnalysisMapper.addVisualModelInfo(visualJsonList);
}
}

+ 3
- 2
src/main/resources/mapper/ResultAnalysisMapper.xml View File

@ -56,7 +56,7 @@
<insert id="addVisualModelInfo" parameterType="java.util.List">
INSERT INTO result_analysis
( res_status, filter, objectId, task_patrol_id, business_id,alg_type,res_img_url)
( res_status, filter, objectId, task_patrol_id, business_id,alg_type,res_img_url,description)
VALUES
<foreach collection="list" item="item" separator=",">
(
@ -66,7 +66,8 @@
#{item.taskPatrolId},
#{item.businessId},
#{item.useType},
#{item.imgUrl}
#{item.imgUrl},
#{item.description}
)
</foreach>
</insert>


Loading…
Cancel
Save