招标解析功能

This commit is contained in:
cwchen 2025-11-26 16:46:54 +08:00
parent f41c2c30dd
commit 92aad5f72d
12 changed files with 204 additions and 11 deletions

View File

@ -61,7 +61,7 @@ public class AnalysisController extends BaseController {
@GetMapping("getBidList")
@SysLog(title = "招标解析", module = "招标解析->查看标段详情", businessType = OperaType.QUERY, details = "查看标段详情", logType = 1)
@RequiresPermissions("analysis:analysis:query")
public TableDataInfo getBidList(AnalysisDto.TemplateDto dto) {
public TableDataInfo getBidList(AnalysisDto dto) {
startPage();
List<AnalysisBidVo> list = analysisService.getBidList(dto);
return getDataTable(list);

View File

@ -2,12 +2,17 @@
package com.bonus.web.service.analysis;
import com.bonus.analysis.service.IASAnalysisService;
import com.bonus.common.constant.TableConstants;
import com.bonus.common.core.domain.AjaxResult;
import com.bonus.common.domain.analysis.dto.AnalysisBidDto;
import com.bonus.common.domain.analysis.dto.AnalysisDto;
import com.bonus.common.domain.analysis.dto.AnalysisProDto;
import com.bonus.common.domain.analysis.po.ProComposition;
import com.bonus.common.domain.analysis.vo.AnalysisBidVo;
import com.bonus.common.domain.analysis.vo.AnalysisVo;
import com.bonus.common.domain.file.po.ResourceFilePo;
import com.bonus.common.domain.file.vo.ResourceFileVo;
import com.bonus.common.domain.file.vo.SysFile;
import com.bonus.common.domain.mainDatabase.dto.EnterpriseDto;
import com.bonus.common.domain.ocr.dto.OcrRequest;
import com.bonus.common.domain.ocr.vo.WordConvertPdfResponse;
@ -16,10 +21,13 @@ import com.bonus.common.utils.Base64ToPdfConverter;
import com.bonus.common.utils.FileUtil;
import com.bonus.common.utils.ValidatorsUtils;
import com.bonus.common.utils.uuid.UUID;
import com.bonus.file.service.FileUploadService;
import com.bonus.file.service.SourceFileService;
import com.bonus.ocr.service.OcrService;
import com.bonus.ocr.service.WordConvertPdfService;
import com.bonus.web.rabbitmq.producer.RabbitMQProducerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -28,7 +36,9 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@ -63,6 +73,12 @@ public class AnalysisService {
@Resource(name = "WordConvertPdfService")
private WordConvertPdfService wordConvertPdfService;
@Resource(name = "SourceFileService")
private SourceFileService sourceFileService;
@Resource(name = "FileUploadService")
private FileUploadService fileUploadService;
public AjaxResult testAsyncMq() {
/*taskExecutor.submit(() -> {
@ -126,10 +142,25 @@ public class AnalysisService {
}
// 保存项目数据
analysisService.addProData(dto);
List<ProComposition> compositions = new ArrayList<>();
for (String uploadType : dto.getUploadType()) {
ProComposition vo = createVo(dto.getProId(), uploadType);
compositions.add(vo);
}
// 保存项目的文件组成数据
analysisService.addProCompositionData(compositions);
// 添加文件
for (int i = 0; i < compositions.size(); i++) {
Long id = compositions.get(i).getId();
dto.getFiles().get(i).setBusinessId(id);
dto.getFiles().get(i).setSourceTable(TableConstants.TB_PRO_COMPOSITION);
}
sourceFileService.saveResourceFile(dto.getFiles());
// 同步解析规则数据
// 执行异步解析任务
CompletableFuture.runAsync(() -> {
}, taskExecutor);
/*CompletableFuture.runAsync(() -> {
}, taskExecutor);*/
return AjaxResult.success();
} catch (Exception e) {
log.error(e.toString(),e);
@ -138,6 +169,13 @@ public class AnalysisService {
}
}
public ProComposition createVo(Long proId,String value){
ProComposition proComposition = new ProComposition();
proComposition.setProId(proId);
proComposition.setCompositionFileName(value);
return proComposition;
}
/**
* 招标解析->查看详情
* @param dto
@ -145,7 +183,7 @@ public class AnalysisService {
* @author cwchen
* @date 2025/11/25 16:08
*/
public List<AnalysisBidVo> getBidList(AnalysisDto.TemplateDto dto) {
public List<AnalysisBidVo> getBidList(AnalysisDto dto) {
return analysisService.getBidList(dto);
}
@ -172,6 +210,27 @@ public class AnalysisService {
*/
public AjaxResult getProDetail(AnalysisDto.TemplateDto dto) {
AnalysisVo analysisVo = analysisService.getProDetail(dto);
// 查询类型为2时查询文件
if(dto.getQueryType() == 2){
// 查询项目组成文件
List<ProComposition> compositions = analysisService.getProComposition(dto);
// 查询招标文件
// 3.查询项目关联资源文件
for (ProComposition composition : compositions) {
List<ResourceFileVo> fileVoList = sourceFileService.getFilesByTable(composition.getId(), TableConstants.TB_PRO_COMPOSITION);
// 4.取minio中的文件访问路径
if(CollectionUtils.isNotEmpty(fileVoList)){
for (ResourceFileVo file : fileVoList) {
SysFile sysFile = fileUploadService.getFile(file.getFilePath());
if(Objects.nonNull(sysFile)){
file.setLsFilePath(sysFile.getUrl());
}
}
}
composition.setFileVoList(fileVoList);
}
analysisVo.setCompositions(compositions);
}
return AjaxResult.success(analysisVo);
}

View File

@ -3,6 +3,7 @@ package com.bonus.analysis.mapper;
import com.bonus.common.domain.analysis.dto.AnalysisBidDto;
import com.bonus.common.domain.analysis.dto.AnalysisDto;
import com.bonus.common.domain.analysis.dto.AnalysisProDto;
import com.bonus.common.domain.analysis.po.ProComposition;
import com.bonus.common.domain.analysis.vo.AnalysisBidVo;
import com.bonus.common.domain.analysis.vo.AnalysisVo;
import org.springframework.stereotype.Repository;
@ -43,7 +44,7 @@ public interface IASAnalysisMapper {
* @author cwchen
* @date 2025/11/25 16:27
*/
List<AnalysisBidVo> getBidList(AnalysisDto.TemplateDto dto);
List<AnalysisBidVo> getBidList(AnalysisDto dto);
/**
* 招标解析->查看项目详情
@ -71,4 +72,22 @@ public interface IASAnalysisMapper {
* @date 2025/11/26 9:39
*/
void editBidData(AnalysisBidDto dto);
/**
* 保存项目的文件组成
* @param compositions
* @return void
* @author cwchen
* @date 2025/11/26 15:43
*/
void addProCompositionData(List<ProComposition> compositions);
/**
* 查询项目文件组成详情
* @param dto
* @return List<ProComposition>
* @author cwchen
* @date 2025/11/26 15:55
*/
List<ProComposition> getProComposition(AnalysisDto.TemplateDto dto);
}

View File

@ -3,6 +3,7 @@ package com.bonus.analysis.service;
import com.bonus.common.domain.analysis.dto.AnalysisBidDto;
import com.bonus.common.domain.analysis.dto.AnalysisDto;
import com.bonus.common.domain.analysis.dto.AnalysisProDto;
import com.bonus.common.domain.analysis.po.ProComposition;
import com.bonus.common.domain.analysis.vo.AnalysisBidVo;
import com.bonus.common.domain.analysis.vo.AnalysisVo;
@ -42,7 +43,7 @@ public interface IASAnalysisService {
* @author cwchen
* @date 2025/11/25 16:27
*/
List<AnalysisBidVo> getBidList(AnalysisDto.TemplateDto dto);
List<AnalysisBidVo> getBidList(AnalysisDto dto);
/**
* 招标解析->查看项目详情
@ -70,4 +71,21 @@ public interface IASAnalysisService {
* @date 2025/11/26 9:38
*/
void editBidData(AnalysisBidDto dto);
/**
* 保存项目的文件组成
* @param compositions
* @return void
* @author cwchen
* @date 2025/11/26 15:43
*/
void addProCompositionData(List<ProComposition> compositions);
/**
* 查询项目组成文件
* @return List<ProComposition>
* @author cwchen
* @date 2025/11/26 15:54
*/
List<ProComposition> getProComposition(AnalysisDto.TemplateDto dto);
}

View File

@ -5,12 +5,14 @@ import com.bonus.analysis.service.IASAnalysisService;
import com.bonus.common.domain.analysis.dto.AnalysisBidDto;
import com.bonus.common.domain.analysis.dto.AnalysisDto;
import com.bonus.common.domain.analysis.dto.AnalysisProDto;
import com.bonus.common.domain.analysis.po.ProComposition;
import com.bonus.common.domain.analysis.vo.AnalysisBidVo;
import com.bonus.common.domain.analysis.vo.AnalysisVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@ -40,7 +42,7 @@ public class ASAnalysisServiceImpl implements IASAnalysisService {
}
@Override
public List<AnalysisBidVo> getBidList(AnalysisDto.TemplateDto dto) {
public List<AnalysisBidVo> getBidList(AnalysisDto dto) {
return analysisMapper.getBidList(dto);
}
@ -62,4 +64,18 @@ public class ASAnalysisServiceImpl implements IASAnalysisService {
public void editBidData(AnalysisBidDto dto) {
analysisMapper.editBidData(dto);
}
@Override
public void addProCompositionData(List<ProComposition> compositions) {
analysisMapper.addProCompositionData(compositions);
}
@Override
public List<ProComposition> getProComposition(AnalysisDto.TemplateDto dto) {
try {
return Optional.ofNullable(analysisMapper.getProComposition(dto)).orElse(new ArrayList());
} catch (Exception e) {
return new ArrayList<>();
}
}
}

View File

@ -56,6 +56,15 @@
parsing_state AS parsingState
FROM tb_pro_bid
WHERE pro_id = #{proId} AND del_flag = '0'
<if test="markName!=null and markName!=''">
AND INSTR(mark_name , #{markName}) > 0
</if>
<if test="bidName!=null and bidName!=''">
AND INSTR(bid_name , #{bidName}) > 0
</if>
<if test="parsingState!=null and parsingState!=''">
AND parsing_state = #{parsingState}
</if>
ORDER BY create_time DESC
</select>
@ -87,4 +96,22 @@
bid_name = #{bidName},maximum_bid_limit = #{maximumBidLimit},safety_const_fee = #{safetyConstFee},
bid_bond = #{bidBond},duration = #{duration},bidding_stage = #{biddingStage} WHERE bid_id = #{bidId}
</update>
<!--保存项目的文件组成-->
<insert id="addProCompositionData" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO tb_pro_composition (pro_id, composition_file_name) VALUES
<foreach collection="list" separator="," item="item">
(
#{item.proId},
#{item.compositionFileName}
)
</foreach>
</insert>
<!--查询项目文件组成详情-->
<select id="getProComposition" resultType="com.bonus.common.domain.analysis.po.ProComposition">
SELECT id,
composition_file_name AS compositionFileName
FROM tb_pro_composition WHERE pro_id = #{proId}
</select>
</mapper>

View File

@ -36,4 +36,7 @@ public class TableConstants {
/**模板组成*/
public static final String TB_TEMPLATE_COMPOSITION = "tb_template_composition";
/**项目文件组成表*/
public static final String TB_PRO_COMPOSITION = "tb_pro_composition";
}

View File

@ -23,6 +23,14 @@ import java.util.Optional;
@Data
public class AnalysisDto {
/*项目id*/
private Long proId;
/**标的名称*/
private String markName;
/**标段名称*/
private String bidName;
/**解析状态*/
private String parsingState;
/**项目名称*/
private String proName;
/**招标人*/
@ -45,6 +53,12 @@ public class AnalysisDto {
@NotNull(message = "模板不能为空", groups = {ADD.class})
private Long templateId;
/**文件组成名称*/
private String[] uploadType;
/**类型为2时查询文件组成*/
private int queryType;
/**
* 创建人
*/

View File

@ -0,0 +1,29 @@
package com.bonus.common.domain.analysis.po;
import com.bonus.common.domain.file.vo.ResourceFileVo;
import lombok.Data;
import java.util.List;
/**
* @className:ProComposition
* @author:cwchen
* @date:2025-11-26-15:36
* @version:1.0
* @description:项目文件组成
*/
@Data
public class ProComposition {
/**工程id*/
private Long id;
/**工程id*/
private Long proId;
/**文件组成名称*/
private String compositionFileName;
/**文件*/
List<ResourceFileVo> fileVoList;
}

View File

@ -1,5 +1,7 @@
package com.bonus.common.domain.analysis.vo;
import com.bonus.common.domain.analysis.po.ProComposition;
import com.bonus.common.domain.file.vo.ResourceFileVo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
@ -86,4 +88,7 @@ public class AnalysisVo {
* 标段list
* */
private List<AnalysisBidVo> bidList;
/**文件组成*/
List<ProComposition> compositions;
}

View File

@ -113,7 +113,7 @@ public class EnterpriseDto {
* 法人联系方式
*/
@Length(max = 11, message = "法人联系方式字符长度不能超过11", groups = {ADD.class, UPDATE.class})
@Pattern(regexp = "^(?:(?:\\+|00)?86)?1[3-9]\\d{9}$",message = "法人联系方式格式不正确", groups = {ADD.class, UPDATE.class})
@Pattern(regexp = "^(|(?:(?:\\+|00)?86)?1[3-9]\\d{9})$", message = "法人联系方式格式不正确", groups = {ADD.class, UPDATE.class})
private String legalPersonPhone;
/**

View File

@ -77,7 +77,8 @@ public class OcrService {
return executeOcrRequest(httpPost);
} catch (IOException e) {
log.error("调用OCR服务失败", e);
throw new IOException("OCR服务调用失败: " + e.getMessage(), e);
// throw new IOException("OCR服务调用失败: " + e.getMessage(), e);
return null;
} finally {
cleanupResources(ocrRequest, httpPost);
}
@ -156,7 +157,8 @@ public class OcrService {
// 检查HTTP状态码
if (statusCode != 200) {
log.error("OCR服务HTTP请求失败状态码: {}, 响应: {}", statusCode, responseBody);
throw new IOException("OCR服务HTTP请求失败状态码: " + statusCode);
// throw new IOException("OCR服务HTTP请求失败状态码: " + statusCode);
return null;
}
OcrResponse ocrResponse = parseResponseBody(responseBody);
@ -181,7 +183,8 @@ public class OcrService {
return objectMapper.readValue(responseBody, OcrResponse.class);
} catch (IOException e) {
log.error("解析OCR响应失败响应内容: {}", responseBody, e);
throw new IOException("解析OCR响应失败: " + e.getMessage(), e);
// throw new IOException("解析OCR响应失败: " + e.getMessage(), e);
return null;
}
}