From 807ddbe5cb68b1a2af52ebf188ad6b12dff39d06 Mon Sep 17 00:00:00 2001 From: v-zhangjc9 Date: Mon, 16 Jun 2025 13:38:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(ai-web):=20=E5=AE=8C=E6=88=90=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E5=92=8C=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...guration.java => FileStoreProperties.java} | 2 +- .../ai/web/controller/DataFileController.java | 16 +++---- .../feedback/FeedbackController.java | 44 +++++++++++++---- .../web/service/feedback/FeedbackService.java | 4 +- .../src/main/resources/application.yml | 2 +- .../client/src/pages/ai/feedback/Feedback.tsx | 48 +++++++++++++++---- 6 files changed, 86 insertions(+), 30 deletions(-) rename service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/configuration/{FileStoreConfiguration.java => FileStoreProperties.java} (91%) diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/configuration/FileStoreConfiguration.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/configuration/FileStoreProperties.java similarity index 91% rename from service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/configuration/FileStoreConfiguration.java rename to service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/configuration/FileStoreProperties.java index b29e48a..867760c 100644 --- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/configuration/FileStoreConfiguration.java +++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/configuration/FileStoreProperties.java @@ -11,7 +11,7 @@ import org.springframework.context.annotation.Configuration; @Data @Configuration @ConfigurationProperties(prefix = "file-store") -public class FileStoreConfiguration { +public class FileStoreProperties { private String downloadPrefix; private String uploadPath; } diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/DataFileController.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/DataFileController.java index f3b4876..d1643af 100644 --- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/DataFileController.java +++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/DataFileController.java @@ -7,7 +7,7 @@ import cn.hutool.core.util.URLUtil; import cn.hutool.crypto.SecureUtil; import com.fasterxml.jackson.annotation.JsonProperty; 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.service.DataFileService; import jakarta.servlet.http.HttpServletResponse; @@ -41,17 +41,17 @@ import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/upload") public class DataFileController { - private final FileStoreConfiguration fileStoreConfiguration; + private final FileStoreProperties fileStoreProperties; private final DataFileService dataFileService; private final String uploadFolderPath; private final String cacheFolderPath; private final String sliceFolderPath; - public DataFileController(FileStoreConfiguration fileStoreConfiguration, DataFileService dataFileService) { - this.fileStoreConfiguration = fileStoreConfiguration; + public DataFileController(FileStoreProperties fileStoreProperties, DataFileService dataFileService) { + this.fileStoreProperties = fileStoreProperties; this.dataFileService = dataFileService; - this.uploadFolderPath = fileStoreConfiguration.getUploadPath(); + this.uploadFolderPath = fileStoreProperties.getUploadPath(); this.cacheFolderPath = StrUtil.format("{}/cache", uploadFolderPath); this.sliceFolderPath = StrUtil.format("{}/slice", uploadFolderPath); } @@ -60,7 +60,7 @@ public class DataFileController { public AmisResponse upload(@RequestParam("file") MultipartFile file) throws IOException { String filename = file.getOriginalFilename(); 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(); String originMd5 = SecureUtil.md5(new ByteArrayInputStream(bytes)); File targetFile = new File(StrUtil.format("{}/{}", uploadFolderPath, originMd5)); @@ -80,7 +80,7 @@ public class DataFileController { } @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); File targetFile = new File(dataFile.getPath()); response.setHeader("Content-Type", dataFile.getType()); @@ -157,7 +157,7 @@ public class DataFileController { request.uploadId, request.filename, request.uploadId.toString(), - StrUtil.format("{}/upload/download/{}", fileStoreConfiguration.getDownloadPrefix(), request.uploadId) + StrUtil.format("{}/upload/download/{}", fileStoreProperties.getDownloadPrefix(), request.uploadId) )); } else { throw new RuntimeException("合并文件失败"); diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/feedback/FeedbackController.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/feedback/FeedbackController.java index 2615add..64cea79 100644 --- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/feedback/FeedbackController.java +++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/controller/feedback/FeedbackController.java @@ -1,13 +1,19 @@ package com.lanyuanxiaoyao.service.ai.web.controller.feedback; 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.web.configuration.FileStoreProperties; +import com.lanyuanxiaoyao.service.ai.web.entity.Feedback; import com.lanyuanxiaoyao.service.ai.web.service.feedback.FeedbackService; +import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.list.ImmutableList; import org.springframework.web.bind.annotation.GetMapping; 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.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -16,27 +22,49 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("feedback") public class FeedbackController { + private final FileStoreProperties fileStoreProperties; private final FeedbackService feedbackService; - public FeedbackController(FeedbackService feedbackService) { + public FeedbackController(FileStoreProperties fileStoreProperties, FeedbackService feedbackService) { + this.fileStoreProperties = fileStoreProperties; this.feedbackService = feedbackService; } @PostMapping("add") - public void add( - @RequestParam("source") String source, - @RequestParam(value = "pictures", required = false) ImmutableList pictures - ) { - feedbackService.add(source, ObjectUtil.defaultIfNull(pictures, Lists.immutable.empty())); + public void add(@RequestBody CreateItem item) { + log.info("Enter method: add[item]. item:{}", item); + feedbackService.add(item.source, ObjectUtil.defaultIfNull(item.pictures, Lists.immutable.empty())); } @GetMapping("list") - public AmisResponse list() { - return AmisResponse.responseCrudData(feedbackService.list()); + public AmisCrudResponse list() { + return AmisResponse.responseCrudData(feedbackService.list().collect(feedback -> new ListItem(fileStoreProperties, feedback))); } @GetMapping("delete") public void delete(@RequestParam("id") Long id) { feedbackService.remove(id); } + + @Data + public static final class CreateItem { + private String source; + private ImmutableList pictures; + } + + @Data + public static final class ListItem { + private Long id; + private String source; + private ImmutableList 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(); + } + } } diff --git a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/feedback/FeedbackService.java b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/feedback/FeedbackService.java index 36f6a60..d16145a 100644 --- a/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/feedback/FeedbackService.java +++ b/service-ai/service-ai-web/src/main/java/com/lanyuanxiaoyao/service/ai/web/service/feedback/FeedbackService.java @@ -51,9 +51,7 @@ public class FeedbackService { .precompileSql(), SnowflakeId.next(), source, - ObjectUtil.isEmpty(pictureIds) - ? null - : pictureIds.makeString(",") + ObjectUtil.isEmpty(pictureIds) ? null : pictureIds.makeString(",") ); } diff --git a/service-cli/service-cli-runner/src/main/resources/application.yml b/service-cli/service-cli-runner/src/main/resources/application.yml index 7b5abea..3fcc8d8 100644 --- a/service-cli/service-cli-runner/src/main/resources/application.yml +++ b/service-cli/service-cli-runner/src/main/resources/application.yml @@ -169,7 +169,7 @@ deploy: jdk: "jdk17" replicas: 1 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 "[spring.datasource.url]": ${deploy.runtime.database.config.url} "[spring.datasource.username]": ${deploy.runtime.database.config.username} diff --git a/service-web/client/src/pages/ai/feedback/Feedback.tsx b/service-web/client/src/pages/ai/feedback/Feedback.tsx index 449d49f..82c6487 100644 --- a/service-web/client/src/pages/ai/feedback/Feedback.tsx +++ b/service-web/client/src/pages/ai/feedback/Feedback.tsx @@ -1,9 +1,25 @@ 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 = () => { return ( -
+ {amisRender( { type: 'page', @@ -28,10 +44,7 @@ const Feedback: React.FC = () => { body: { debug: commonInfo.debug, type: 'form', - api: { - url: `${commonInfo.baseAiUrl}/feedback/add`, - dataType: 'form', - }, + api: `${commonInfo.baseAiUrl}/feedback/add`, body: [ { type: 'editor', @@ -50,12 +63,14 @@ const Feedback: React.FC = () => { label: '相关截图', autoUpload: false, multiple: true, + joinValues: false, + extractValue: true, // 5MB 5242880 // 100MB 104857600 // 500MB 524288000 // 1GB 1073741824 maxSize: 5242880, - receiver: `${commonInfo.baseAiUrl}/upload` + receiver: `${commonInfo.baseAiUrl}/upload`, }, ], }, @@ -66,11 +81,26 @@ const Feedback: React.FC = () => { { name: 'id', label: '编号', + width: 150, + }, + { + name: 'source', + label: '故障描述', + }, + { + name: 'pictures', + label: '相关截图', + width: 200, + className: 'feedback-list-images', + type: 'images', + enlargeAble: true, + enlargeWithGallary: true, }, { - name: 'status', label: '状态', width: 80, + align: 'center', + ...mappingField('status', statusMapping), }, { type: 'operation', @@ -101,7 +131,7 @@ const Feedback: React.FC = () => { ], }, )} -
+ ) }