feat(ai-web): 完成图片上传和显示
This commit is contained in:
@@ -11,7 +11,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
@Data
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "file-store")
|
@ConfigurationProperties(prefix = "file-store")
|
||||||
public class FileStoreConfiguration {
|
public class FileStoreProperties {
|
||||||
private String downloadPrefix;
|
private String downloadPrefix;
|
||||||
private String uploadPath;
|
private String uploadPath;
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ import cn.hutool.core.util.URLUtil;
|
|||||||
import cn.hutool.crypto.SecureUtil;
|
import cn.hutool.crypto.SecureUtil;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisResponse;
|
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisResponse;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.configuration.FileStoreConfiguration;
|
import com.lanyuanxiaoyao.service.ai.web.configuration.FileStoreProperties;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.entity.vo.DataFileVO;
|
import com.lanyuanxiaoyao.service.ai.web.entity.vo.DataFileVO;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.service.DataFileService;
|
import com.lanyuanxiaoyao.service.ai.web.service.DataFileService;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
@@ -41,17 +41,17 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/upload")
|
@RequestMapping("/upload")
|
||||||
public class DataFileController {
|
public class DataFileController {
|
||||||
private final FileStoreConfiguration fileStoreConfiguration;
|
private final FileStoreProperties fileStoreProperties;
|
||||||
private final DataFileService dataFileService;
|
private final DataFileService dataFileService;
|
||||||
private final String uploadFolderPath;
|
private final String uploadFolderPath;
|
||||||
private final String cacheFolderPath;
|
private final String cacheFolderPath;
|
||||||
private final String sliceFolderPath;
|
private final String sliceFolderPath;
|
||||||
|
|
||||||
public DataFileController(FileStoreConfiguration fileStoreConfiguration, DataFileService dataFileService) {
|
public DataFileController(FileStoreProperties fileStoreProperties, DataFileService dataFileService) {
|
||||||
this.fileStoreConfiguration = fileStoreConfiguration;
|
this.fileStoreProperties = fileStoreProperties;
|
||||||
this.dataFileService = dataFileService;
|
this.dataFileService = dataFileService;
|
||||||
|
|
||||||
this.uploadFolderPath = fileStoreConfiguration.getUploadPath();
|
this.uploadFolderPath = fileStoreProperties.getUploadPath();
|
||||||
this.cacheFolderPath = StrUtil.format("{}/cache", uploadFolderPath);
|
this.cacheFolderPath = StrUtil.format("{}/cache", uploadFolderPath);
|
||||||
this.sliceFolderPath = StrUtil.format("{}/slice", uploadFolderPath);
|
this.sliceFolderPath = StrUtil.format("{}/slice", uploadFolderPath);
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ public class DataFileController {
|
|||||||
public AmisResponse<FinishResponse> upload(@RequestParam("file") MultipartFile file) throws IOException {
|
public AmisResponse<FinishResponse> upload(@RequestParam("file") MultipartFile file) throws IOException {
|
||||||
String filename = file.getOriginalFilename();
|
String filename = file.getOriginalFilename();
|
||||||
Long id = dataFileService.initialDataFile(filename);
|
Long id = dataFileService.initialDataFile(filename);
|
||||||
String url = StrUtil.format("{}/upload/download/{}", fileStoreConfiguration.getDownloadPrefix(), id);
|
String url = StrUtil.format("{}/upload/download/{}", fileStoreProperties.getDownloadPrefix(), id);
|
||||||
byte[] bytes = file.getBytes();
|
byte[] bytes = file.getBytes();
|
||||||
String originMd5 = SecureUtil.md5(new ByteArrayInputStream(bytes));
|
String originMd5 = SecureUtil.md5(new ByteArrayInputStream(bytes));
|
||||||
File targetFile = new File(StrUtil.format("{}/{}", uploadFolderPath, originMd5));
|
File targetFile = new File(StrUtil.format("{}/{}", uploadFolderPath, originMd5));
|
||||||
@@ -80,7 +80,7 @@ public class DataFileController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/download/{id}")
|
@GetMapping("/download/{id}")
|
||||||
public void download(@PathVariable Long id, HttpServletResponse response) throws IOException {
|
public void download(@PathVariable("id") Long id, HttpServletResponse response) throws IOException {
|
||||||
DataFileVO dataFile = dataFileService.downloadFile(id);
|
DataFileVO dataFile = dataFileService.downloadFile(id);
|
||||||
File targetFile = new File(dataFile.getPath());
|
File targetFile = new File(dataFile.getPath());
|
||||||
response.setHeader("Content-Type", dataFile.getType());
|
response.setHeader("Content-Type", dataFile.getType());
|
||||||
@@ -157,7 +157,7 @@ public class DataFileController {
|
|||||||
request.uploadId,
|
request.uploadId,
|
||||||
request.filename,
|
request.filename,
|
||||||
request.uploadId.toString(),
|
request.uploadId.toString(),
|
||||||
StrUtil.format("{}/upload/download/{}", fileStoreConfiguration.getDownloadPrefix(), request.uploadId)
|
StrUtil.format("{}/upload/download/{}", fileStoreProperties.getDownloadPrefix(), request.uploadId)
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("合并文件失败");
|
throw new RuntimeException("合并文件失败");
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
package com.lanyuanxiaoyao.service.ai.web.controller.feedback;
|
package com.lanyuanxiaoyao.service.ai.web.controller.feedback;
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisCrudResponse;
|
||||||
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisResponse;
|
import com.lanyuanxiaoyao.service.ai.core.entity.amis.AmisResponse;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.configuration.FileStoreProperties;
|
||||||
|
import com.lanyuanxiaoyao.service.ai.web.entity.Feedback;
|
||||||
import com.lanyuanxiaoyao.service.ai.web.service.feedback.FeedbackService;
|
import com.lanyuanxiaoyao.service.ai.web.service.feedback.FeedbackService;
|
||||||
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.collections.api.factory.Lists;
|
import org.eclipse.collections.api.factory.Lists;
|
||||||
import org.eclipse.collections.api.list.ImmutableList;
|
import org.eclipse.collections.api.list.ImmutableList;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
@@ -16,27 +22,49 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("feedback")
|
@RequestMapping("feedback")
|
||||||
public class FeedbackController {
|
public class FeedbackController {
|
||||||
|
private final FileStoreProperties fileStoreProperties;
|
||||||
private final FeedbackService feedbackService;
|
private final FeedbackService feedbackService;
|
||||||
|
|
||||||
public FeedbackController(FeedbackService feedbackService) {
|
public FeedbackController(FileStoreProperties fileStoreProperties, FeedbackService feedbackService) {
|
||||||
|
this.fileStoreProperties = fileStoreProperties;
|
||||||
this.feedbackService = feedbackService;
|
this.feedbackService = feedbackService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("add")
|
@PostMapping("add")
|
||||||
public void add(
|
public void add(@RequestBody CreateItem item) {
|
||||||
@RequestParam("source") String source,
|
log.info("Enter method: add[item]. item:{}", item);
|
||||||
@RequestParam(value = "pictures", required = false) ImmutableList<Long> pictures
|
feedbackService.add(item.source, ObjectUtil.defaultIfNull(item.pictures, Lists.immutable.empty()));
|
||||||
) {
|
|
||||||
feedbackService.add(source, ObjectUtil.defaultIfNull(pictures, Lists.immutable.empty()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("list")
|
@GetMapping("list")
|
||||||
public AmisResponse<?> list() {
|
public AmisCrudResponse list() {
|
||||||
return AmisResponse.responseCrudData(feedbackService.list());
|
return AmisResponse.responseCrudData(feedbackService.list().collect(feedback -> new ListItem(fileStoreProperties, feedback)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("delete")
|
@GetMapping("delete")
|
||||||
public void delete(@RequestParam("id") Long id) {
|
public void delete(@RequestParam("id") Long id) {
|
||||||
feedbackService.remove(id);
|
feedbackService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static final class CreateItem {
|
||||||
|
private String source;
|
||||||
|
private ImmutableList<Long> pictures;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static final class ListItem {
|
||||||
|
private Long id;
|
||||||
|
private String source;
|
||||||
|
private ImmutableList<String> pictures;
|
||||||
|
private Feedback.Status status;
|
||||||
|
|
||||||
|
public ListItem(FileStoreProperties fileStoreProperties, Feedback feedback) {
|
||||||
|
this.id = feedback.getId();
|
||||||
|
this.source = feedback.getSource();
|
||||||
|
this.pictures = feedback.getPictureIds()
|
||||||
|
.collect(id -> StrUtil.format("{}/upload/download/{}", fileStoreProperties.getDownloadPrefix(), id));
|
||||||
|
this.status = feedback.getStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,9 +51,7 @@ public class FeedbackService {
|
|||||||
.precompileSql(),
|
.precompileSql(),
|
||||||
SnowflakeId.next(),
|
SnowflakeId.next(),
|
||||||
source,
|
source,
|
||||||
ObjectUtil.isEmpty(pictureIds)
|
ObjectUtil.isEmpty(pictureIds) ? null : pictureIds.makeString(",")
|
||||||
? null
|
|
||||||
: pictureIds.makeString(",")
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ deploy:
|
|||||||
jdk: "jdk17"
|
jdk: "jdk17"
|
||||||
replicas: 1
|
replicas: 1
|
||||||
arguments:
|
arguments:
|
||||||
"[file-store.download-prefix]": 'http://132.126.207.130:35690/hudi_services/ai_knowledge'
|
"[file-store.download-prefix]": 'http://132.126.207.130:35690/hudi_services/service_ai_web'
|
||||||
"[file-store.upload-path]": ${deploy.runtime.data-path}/knowledge
|
"[file-store.upload-path]": ${deploy.runtime.data-path}/knowledge
|
||||||
"[spring.datasource.url]": ${deploy.runtime.database.config.url}
|
"[spring.datasource.url]": ${deploy.runtime.database.config.url}
|
||||||
"[spring.datasource.username]": ${deploy.runtime.database.config.username}
|
"[spring.datasource.username]": ${deploy.runtime.database.config.username}
|
||||||
|
|||||||
@@ -1,9 +1,25 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {amisRender, commonInfo, crudCommonOptions} from '../../../util/amis.tsx'
|
import styled from 'styled-components'
|
||||||
|
import {amisRender, commonInfo, crudCommonOptions, mappingField, mappingItem} from '../../../util/amis.tsx'
|
||||||
|
|
||||||
|
const FeedbackDiv = styled.div`
|
||||||
|
.feedback-list-images {
|
||||||
|
.antd-Img-container {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const statusMapping = [
|
||||||
|
mappingItem('分析中', 'ANALYSIS_PROCESSING', 'label-warning'),
|
||||||
|
mappingItem('分析完成', 'ANALYSIS_SUCCESS', 'label-primary'),
|
||||||
|
mappingItem('处理完成', 'FINISHED', 'label-success'),
|
||||||
|
]
|
||||||
|
|
||||||
const Feedback: React.FC = () => {
|
const Feedback: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<div className="feedback">
|
<FeedbackDiv className="feedback">
|
||||||
{amisRender(
|
{amisRender(
|
||||||
{
|
{
|
||||||
type: 'page',
|
type: 'page',
|
||||||
@@ -28,10 +44,7 @@ const Feedback: React.FC = () => {
|
|||||||
body: {
|
body: {
|
||||||
debug: commonInfo.debug,
|
debug: commonInfo.debug,
|
||||||
type: 'form',
|
type: 'form',
|
||||||
api: {
|
api: `${commonInfo.baseAiUrl}/feedback/add`,
|
||||||
url: `${commonInfo.baseAiUrl}/feedback/add`,
|
|
||||||
dataType: 'form',
|
|
||||||
},
|
|
||||||
body: [
|
body: [
|
||||||
{
|
{
|
||||||
type: 'editor',
|
type: 'editor',
|
||||||
@@ -50,12 +63,14 @@ const Feedback: React.FC = () => {
|
|||||||
label: '相关截图',
|
label: '相关截图',
|
||||||
autoUpload: false,
|
autoUpload: false,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
|
joinValues: false,
|
||||||
|
extractValue: true,
|
||||||
// 5MB 5242880
|
// 5MB 5242880
|
||||||
// 100MB 104857600
|
// 100MB 104857600
|
||||||
// 500MB 524288000
|
// 500MB 524288000
|
||||||
// 1GB 1073741824
|
// 1GB 1073741824
|
||||||
maxSize: 5242880,
|
maxSize: 5242880,
|
||||||
receiver: `${commonInfo.baseAiUrl}/upload`
|
receiver: `${commonInfo.baseAiUrl}/upload`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -66,11 +81,26 @@ const Feedback: React.FC = () => {
|
|||||||
{
|
{
|
||||||
name: 'id',
|
name: 'id',
|
||||||
label: '编号',
|
label: '编号',
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'source',
|
||||||
|
label: '故障描述',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pictures',
|
||||||
|
label: '相关截图',
|
||||||
|
width: 200,
|
||||||
|
className: 'feedback-list-images',
|
||||||
|
type: 'images',
|
||||||
|
enlargeAble: true,
|
||||||
|
enlargeWithGallary: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'status',
|
|
||||||
label: '状态',
|
label: '状态',
|
||||||
width: 80,
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
...mappingField('status', statusMapping),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'operation',
|
type: 'operation',
|
||||||
@@ -101,7 +131,7 @@ const Feedback: React.FC = () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
</div>
|
</FeedbackDiv>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user