Browse Source

新增内容

sjj_dev
zhouhaibin 2 weeks ago
parent
commit
c73e646d02
  1. 96
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/TenderTaskResultsController.java
  2. 105
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/TenderTaskTypeController.java
  3. 118
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/TenderTasksController.java
  4. 91
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTaskChild.java
  5. 67
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTaskGroup.java
  6. 51
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTaskResultDetail.java
  7. 62
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTaskType.java
  8. 101
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTasks.java
  9. 87
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/TenderTaskResultDetailBo.java
  10. 51
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/TenderTaskTypeBo.java
  11. 104
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/TenderTasksBo.java
  12. 130
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/TenderTaskResultDetailVo.java
  13. 45
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/TenderTaskResultVO.java
  14. 69
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/TenderTaskTypeVo.java
  15. 150
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/TenderTasksVo.java
  16. 33
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/enums/TenderReviewStatusEnum.java
  17. 14
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/TenderTaskResultDetailMapper.java
  18. 16
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/TenderTaskTypeMapper.java
  19. 41
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/TenderTasksMapper.java
  20. 57
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/ITenderTaskResultsService.java
  21. 68
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/ITenderTaskTypeService.java
  22. 61
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/ITenderTasksService.java
  23. 823
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/TenderTaskResultsServiceImpl.java
  24. 144
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/TenderTaskTypeServiceImpl.java
  25. 347
      zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/TenderTasksServiceImpl.java
  26. 7
      zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/TenderTaskResultDetailMapper.xml
  27. 140
      zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/TenderTasksMapper.xml

96
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/TenderTaskResultsController.java

@ -0,0 +1,96 @@
package org.dromara.productManagement.controller;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.core.domain.R;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.productManagement.domain.vo.TenderTaskResultVO;
import org.dromara.productManagement.service.ITenderTaskResultsService;
import java.util.List;
/**
* 招投标任务结果
*
* @author guoyan
* @date 2024-12-14
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/tenderTask/tenderTaskResults")
public class TenderTaskResultsController extends BaseController {
private final ITenderTaskResultsService tenderTaskResultsService;
/**
* 根据任务ID获取详细的招投标任务结果
*
* @param taskId 任务ID
*/
// @SaCheckPermission("productManagement:TenderTaskResults:query")
@GetMapping("/taskDetail/{taskId}")
public R<List<TenderTaskResultVO>> getDetailResultsByTaskId(@NotNull(message = "任务ID不能为空")
@PathVariable String taskId) {
return R.ok(tenderTaskResultsService.getDetailResultsByTaskId(taskId));
}
/**
* 下载招投标任务结果
*
* @param ids 主键串
*/
// @SaCheckPermission("productManagement:TenderTaskResults:download")
@Log(title = "招投标任务结果", businessType = BusinessType.EXPORT)
@GetMapping("/downloadResult/{ids}")
public void download(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids, HttpServletResponse response) {
tenderTaskResultsService.downloadResult(ids, response);
}
/**
* 获取招投标任务PDF文件流
*
* @param taskId 任务ID
*/
@GetMapping("/getPdfStream/{taskId}")
public void getPdfStream(@NotNull(message = "任务ID不能为空")
@PathVariable String taskId,
HttpServletResponse response) {
tenderTaskResultsService.getPdfStream(taskId, response);
}
/**
* 获取招投标文件PDF文件流
*
* @param taskId 任务ID
*/
@GetMapping("/getBidPdfStream/{taskId}")
public void getBidPdfStream(@NotNull(message = "任务ID不能为空")
@PathVariable String taskId,
HttpServletResponse response) {
tenderTaskResultsService.getBidPdfStream(taskId, response);
}
/**
* 更新招投标任务结果项的状态已读/采纳
*
* @param id 结果项ID
* @param field 字段名isRead/isAdopted
* @param value 0/1
*/
// @SaCheckPermission("productManagement:TenderTaskResults:edit")
@Log(title = "更新招投标任务结果项状态", businessType = BusinessType.UPDATE)
@PutMapping("/updateResultItemStatus/{id}/{field}/{value}")
public R<Void> updateResultItemStatus(
@NotEmpty(message = "ID不能为空") @PathVariable("id") String id,
@NotEmpty(message = "字段名不能为空") @PathVariable("field") String field,
@NotEmpty(message = "值不能为空") @PathVariable("value") String value) {
return toAjax(tenderTaskResultsService.updateResultItemStatus(id, field, value));
}
}

105
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/TenderTaskTypeController.java

@ -0,0 +1,105 @@
package org.dromara.productManagement.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.productManagement.domain.vo.TenderTaskTypeVo;
import org.dromara.productManagement.domain.bo.TenderTaskTypeBo;
import org.dromara.productManagement.service.ITenderTaskTypeService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
* 招投标类型
*
* @author guoyan
* @date 2024-12-14
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/tenderTask/tenderTaskType")
public class TenderTaskTypeController extends BaseController {
private final ITenderTaskTypeService tenderTaskTypeService;
/**
* 查询招投标类型列表
*/
// @SaCheckPermission("productManagement:TenderTaskType:list")
@GetMapping("/list")
public R<List<TenderTaskTypeVo>> list(TenderTaskTypeBo bo) {
return R.ok(tenderTaskTypeService.queryList(bo));
}
/**
* 导出招投标类型列表
*/
// @SaCheckPermission("productManagement:TenderTaskType:export")
@Log(title = "招投标类型", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(TenderTaskTypeBo bo, HttpServletResponse response) {
List<TenderTaskTypeVo> list = tenderTaskTypeService.queryList(bo);
ExcelUtil.exportExcel(list, "招投标类型", TenderTaskTypeVo.class, response);
}
/**
* 获取招投标类型详细信息
*
* @param id 主键
*/
// @SaCheckPermission("productManagement:TenderTaskType:query")
@GetMapping("/{id}")
public R<TenderTaskTypeVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(tenderTaskTypeService.queryById(id));
}
/**
* 新增招投标类型
*/
// @SaCheckPermission("productManagement:TenderTaskType:add")
@Log(title = "招投标类型", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody TenderTaskTypeBo bo) {
return toAjax(tenderTaskTypeService.insertByBo(bo));
}
/**
* 修改招投标类型
*/
// @SaCheckPermission("productManagement:TenderTaskType:edit")
@Log(title = "招投标类型", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TenderTaskTypeBo bo) {
return toAjax(tenderTaskTypeService.updateByBo(bo));
}
/**
* 删除招投标类型
*
* @param ids 主键串
*/
// @SaCheckPermission("productManagement:TenderTaskType:remove")
@Log(title = "招投标类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(tenderTaskTypeService.deleteWithValidByIds(List.of(ids), true));
}
}

118
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/controller/TenderTasksController.java

@ -0,0 +1,118 @@
package org.dromara.productManagement.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.productManagement.domain.TenderTaskGroup;
import org.dromara.productManagement.domain.vo.TenderTasksVo;
import org.dromara.productManagement.domain.bo.TenderTasksBo;
import org.dromara.productManagement.service.ITenderTasksService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.log.enums.BusinessType;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
/**
* 招投标审核任务
*
* @author ruoyi
* @date 2024-01-01
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/tenderTask/tenderTasks")
@Tag(name = "招投标审核任务管理", description = "招投标审核任务管理")
public class TenderTasksController extends BaseController {
private final ITenderTasksService tenderTasksService;
/**
* 查询招投标审核任务列表父子结构
*/
@SaCheckPermission("tender:tasks:list")
@GetMapping("/list")
public TableDataInfo<TenderTaskGroup> list(TenderTasksBo bo, PageQuery pageQuery) {
return tenderTasksService.queryGroupPageList(bo, pageQuery);
}
/**
* 导出招投标审核任务列表
*/
@SaCheckPermission("tender:tasks:export")
@Log(title = "招投标审核任务", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(TenderTasksBo bo, HttpServletResponse response) {
List<TenderTasksVo> list = tenderTasksService.queryList(bo);
ExcelUtil.exportExcel(list, "招投标审核任务", TenderTasksVo.class, response);
}
/**
* 获取招投标审核任务详细信息
*/
@SaCheckPermission("tender:tasks:query")
@GetMapping("/{id}")
public R<TenderTasksVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(tenderTasksService.queryById(id));
}
/**
* 新增招投标审核任务
*/
@SaCheckPermission("tender:tasks:add")
@Log(title = "招投标审核任务", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody TenderTasksBo bo) {
return toAjax(tenderTasksService.insertByBo(bo));
}
/**
* 修改招投标审核任务
*/
@SaCheckPermission("tender:tasks:edit")
@Log(title = "招投标审核任务", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody TenderTasksBo bo) {
return toAjax(tenderTasksService.updateByBo(bo));
}
/**
* 删除招投标审核任务
*/
@SaCheckPermission("tender:tasks:remove")
@Log(title = "招投标审核任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(tenderTasksService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 删除招投标任务文件
*/
@SaCheckPermission("tender:tasks:remove")
@Log(title = "删除招投标任务文件", businessType = BusinessType.DELETE)
@DeleteMapping("/ossRemoveById/{ossid}")
public R<Void> ossRemoveById(@NotEmpty(message = "主键不能为空")
@PathVariable String ossid) {
return toAjax(tenderTasksService.ossRemoveById(ossid, true));
}
}

91
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTaskChild.java

@ -0,0 +1,91 @@
package org.dromara.productManagement.domain;
import lombok.Data;
import java.util.Date;
/**
* 招投标任务子项对象
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
public class TenderTaskChild {
/**
* 任务ID
*/
private Long id;
/**
* 任务名称
*/
private String taskName;
/**
* 招标文件名称
*/
private String tenderDocumentName;
/**
* 投标文件名称
*/
private String bidDocumentName;
/**
* 进展状态
*/
private String progressStatus;
/**
* 任务组ID
*/
private Long groupId;
/**
* 列队任务ID
*/
private String taskId;
/**
* 审核结果
*/
private String resultType;
/**
* 招标文件oss存储id
*/
private String tenderDocOssId;
/**
* 投标文件oss存储id
*/
private String bidDocZipOssId;
/**
* 版本号
*/
private Long version;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 任务持续时间
*/
private String taskDuration;
/**
* 创建用户
*/
private String createUser;
}

67
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTaskGroup.java

@ -0,0 +1,67 @@
package org.dromara.productManagement.domain;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 招投标任务分组对象
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
public class TenderTaskGroup implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 分组ID
*/
private String id;
/**
* 创建者ID
*/
private Long createBy;
/**
* 招标文件名称
*/
private String tenderDocumentName;
/**
* 投标文件名称
*/
private String bidDocumentName;
/**
* 创建时间
*/
private Date createTime;
/**
* 创建用户
*/
private String createUser;
/**
* 进度信息
*/
private String progress;
/**
* 文件删除标志
*/
private String deleteFlag;
/**
* 子任务列表
*/
private List<TenderTaskChild> childrenTasks;
}

51
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTaskResultDetail.java

@ -0,0 +1,51 @@
package org.dromara.productManagement.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 招投标审核结果详情对象 tender_task_result_detail
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("tender_task_result_details")
public class TenderTaskResultDetail extends TenantEntity {
@TableId(value = "id")
private String id;
/**
* 分类id
*/
private String categoryId;
private String issueName; // 问题点名称
private String originalText; // 原文
private String comparedText; // 比对原文
private String modifiedContent; // 修改后的内容
private String modificationDisplay; // 展示修改情况
private String existingIssues; // 存在的问题
private String reviewBasis; // 审查依据
private String isRead; // 是否已读
private String isAdopted; // 是否采纳
/**
* 删除标志
*/
@TableLogic
private String delFlag;
private int sortOrder;
}

62
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTaskType.java

@ -0,0 +1,62 @@
package org.dromara.productManagement.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* 招投标类型对象 tender_task_type
*
* @author guoyan
* @date 2024-12-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("tender_task_type")
public class TenderTaskType extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 类型ID
*/
@TableId(value = "id")
private Long id;
/**
* 招投标类型名称
*/
private String tenderName;
/**
* 显示顺序
*/
private Long sort;
/**
* 状态0正常 1停用
*/
private String status;
/**
* 删除标志0代表存在 1代表删除
*/
@TableLogic
private String delFlag;
/**
* 版本号
*/
@Version
private Long version;
/**
* 备注
*/
private String remark;
}

101
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/TenderTasks.java

@ -0,0 +1,101 @@
package org.dromara.productManagement.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
/**
* 招投标审核任务对象 tender_tasks
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("tender_tasks")
public class TenderTasks extends TenantEntity {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id")
private Long id;
/**
* 任务名称
*/
@NotBlank(message = "任务名称不能为空")
private String taskName;
/**
* 招标文件名称
*/
private String tenderDocumentName;
/**
* 投标文件名称
*/
private String bidDocumentName;
/**
* 进展状态
*/
private String progressStatus;
/**
* 文档是否删除 (Y/N)
*/
private String deleteFlag;
/**
* 删除标志
*/
private String delFlag;
/**
* 版本号
*/
private Long version;
/**
* 创建部门
*/
private Long createDept;
/**
* 任务组ID
*/
private Long groupId;
/**
* 列队任务ID
*/
private String taskId;
/**
* 审核结果
*/
private String resultType;
/**
* 招标文件oss存储id
*/
private String tenderDocOssId;
/**
* 投标文件oss存储id
*/
private String bidDocZipOssId;
/**
* PDF文件路径
*/
private String pdfPath;
}

87
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/TenderTaskResultDetailBo.java

@ -0,0 +1,87 @@
package org.dromara.productManagement.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import org.dromara.productManagement.domain.TenderTaskResultDetail;
/**
* 招投标审核结果详情业务对象 tender_task_result_detail
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = TenderTaskResultDetail.class, reverseConvertGenerate = false)
public class TenderTaskResultDetailBo extends BaseEntity {
/**
* 主键ID
*/
@NotBlank(message = "主键ID不能为空", groups = { EditGroup.class })
private String id;
/**
* 分类id
*/
private String categoryId;
/**
* 问题点名称
*/
private String issueName;
/**
* 原文
*/
private String originalText;
/**
* 比对原文
*/
private String comparedText;
/**
* 修改后的内容
*/
private String modifiedContent;
/**
* 展示修改情况
*/
private String modificationDisplay;
/**
* 存在的问题
*/
private String existingIssues;
/**
* 审查依据
*/
private String reviewBasis;
/**
* 是否已读
*/
private String isRead;
/**
* 是否采纳
*/
private String isAdopted;
/**
* 删除标志
*/
private String delFlag;
private int sortOrder;
}

51
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/TenderTaskTypeBo.java

@ -0,0 +1,51 @@
package org.dromara.productManagement.domain.bo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import org.dromara.common.tenant.core.TenantEntity;
import org.dromara.productManagement.domain.TenderTaskType;
/**
* 招投标类型业务对象
*
* @author guoyan
* @date 2024-12-14
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = TenderTaskType.class, reverseConvertGenerate = false)
public class TenderTaskTypeBo extends TenantEntity {
/**
* 类型ID
*/
@NotNull(message = "类型ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 招投标类型名称
*/
@NotBlank(message = "招投标类型名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String tenderName;
/**
* 显示顺序
*/
private Long sort;
/**
* 状态0正常 1停用
*/
private String status;
/**
* 备注
*/
private String remark;
}

104
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/bo/TenderTasksBo.java

@ -0,0 +1,104 @@
package org.dromara.productManagement.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import org.dromara.productManagement.domain.TenderTasks;
import java.util.List;
/**
* 招投标审核任务业务对象 tender_tasks
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = TenderTasks.class, reverseConvertGenerate = false)
public class TenderTasksBo extends BaseEntity {
/**
* 主键ID
*/
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
private Long id;
/**
* 任务名称
*/
@NotBlank(message = "任务名称不能为空")
private String taskName;
/**
* 任务名称列表用于多选
*/
@NotEmpty(message = "任务名称列表不能为空", groups = { AddGroup.class })
private List<@NotBlank(message = "任务名称不能为空") String> taskNameList;
/**
* 招标文件名称
*/
private String tenderDocumentName;
/**
* 投标文件名称
*/
private String bidDocumentName;
/**
* 进展状态
*/
private String progressStatus;
/**
* 文档是否删除 (Y/N)
*/
private String deleteFlag;
/**
* 删除标志
*/
private String delFlag;
/**
* 版本号
*/
private Long version;
/**
* 创建部门
*/
private Long createDept;
/**
* 任务组ID
*/
private Long groupId;
/**
* 列队任务ID
*/
private String taskId;
/**
* 审核结果
*/
private String resultType;
/**
* 招标文件oss存储id
*/
private String tenderDocOssId;
/**
* 投标文件oss存储id
*/
private String bidDocZipOssId;
}

130
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/TenderTaskResultDetailVo.java

@ -0,0 +1,130 @@
package org.dromara.productManagement.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import lombok.Data;
import org.dromara.productManagement.domain.TenderTaskResultDetail;
import java.util.Date;
/**
* 招投标审核结果详情视图对象 tender_task_result_detail
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = TenderTaskResultDetail.class)
public class TenderTaskResultDetailVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private String id;
/**
* 分类id
*/
@ExcelProperty(value = "分类ID")
private String categoryId;
/**
* 问题点名称
*/
@ExcelProperty(value = "问题点名称")
private String issueName;
/**
* 原文
*/
@ExcelProperty(value = "原文")
private String originalText;
/**
* 比对原文
*/
@ExcelProperty(value = "比对原文")
private String comparedText;
/**
* 修改后的内容
*/
@ExcelProperty(value = "修改后的内容")
private String modifiedContent;
/**
* 展示修改情况
*/
@ExcelProperty(value = "展示修改情况")
private String modificationDisplay;
/**
* 存在的问题
*/
@ExcelProperty(value = "存在的问题")
private String existingIssues;
/**
* 审查依据
*/
@ExcelProperty(value = "审查依据")
private String reviewBasis;
/**
* 是否已读
*/
@ExcelDictFormat(dictType = "is_read")
private String isRead;
/**
* 是否采纳
*/
@ExcelDictFormat(dictType = "is_adopted")
private String isAdopted;
/**
* 删除标志
*/
@ExcelDictFormat(dictType = "del_flag")
private String delFlag;
/**
* 租户ID
*/
@ExcelProperty(value = "租户ID")
private String tenantId;
/**
* 创建人
*/
@ExcelProperty(value = "创建人")
private Long createBy;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
/**
* 更新人
*/
@ExcelProperty(value = "更新人")
private Long updateBy;
/**
* 更新时间
*/
@ExcelProperty(value = "更新时间")
private Date updateTime;
private int sortOrder;
}

45
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/TenderTaskResultVO.java

@ -0,0 +1,45 @@
package org.dromara.productManagement.domain.vo;
import lombok.Data;
import java.util.List;
/**
* 招投标任务结果视图对象
*
* @author guoyan
* @date 2024-12-14
*/
@Data
public class TenderTaskResultVO {
private String name; // 分类名称
private List<ResultItem> results;
@Data
public static class ResultItem {
private String id; // 唯一标识ID
private Integer serialNumber; // 序号
private String issueName; // 问题点名称
private String originalText; // 原文
private String comparedText; // 比对原文
private String modifiedContent; // 修改后的内容
private String modificationDisplay; // 展示修改情况
private String existingIssues; // 存在的问题
private String reviewBasis; // 审查依据(JSON字符串)
private String isRead; // 是否已读
private String isAdopted; // 是否采纳
}
}

69
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/TenderTaskTypeVo.java

@ -0,0 +1,69 @@
package org.dromara.productManagement.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.productManagement.domain.TenderTaskType;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 招投标类型视图对象 tender_task_type
*
* @author guoyan
* @date 2024-12-14
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = TenderTaskType.class)
public class TenderTaskTypeVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 类型ID
*/
@ExcelProperty(value = "类型ID")
private Long id;
/**
* 招投标类型名称
*/
@ExcelProperty(value = "招投标类型名称")
private String tenderName;
/**
* 显示顺序
*/
@ExcelProperty(value = "显示顺序")
private Long sort;
/**
* 状态0正常 1停用
*/
@ExcelDictFormat(readConverterExp = "0=正常,1=停用")
private String status;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}

150
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/domain/vo/TenderTasksVo.java

@ -0,0 +1,150 @@
package org.dromara.productManagement.domain.vo;
import io.github.linpeilie.annotations.AutoMapper;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import lombok.Data;
import org.dromara.productManagement.domain.TenderTasks;
import java.util.Date;
/**
* 招投标审核任务视图对象 tender_tasks
*
* @author ruoyi
* @date 2024-01-01
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = TenderTasks.class)
public class TenderTasksVo {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty(value = "主键ID")
private Long id;
/**
* 任务名称
*/
@ExcelProperty(value = "任务名称")
private String taskName;
/**
* 招标文件名称
*/
@ExcelProperty(value = "招标文件名称")
private String tenderDocumentName;
/**
* 投标文件名称
*/
@ExcelProperty(value = "投标文件名称")
private String bidDocumentName;
/**
* 进展状态
*/
@ExcelProperty(value = "进展状态")
@ExcelDictFormat(dictType = "progress_status")
private String progressStatus;
/**
* 文档是否删除
*/
@ExcelProperty(value = "文档是否删除")
@ExcelDictFormat(dictType = "delete_flag")
private String deleteFlag;
/**
* 删除标志
*/
@ExcelProperty(value = "删除标志")
@ExcelDictFormat(dictType = "del_flag")
private String delFlag;
/**
* 版本号
*/
@ExcelProperty(value = "版本号")
private Long version;
/**
* 租户ID
*/
@ExcelProperty(value = "租户ID")
private String tenantId;
/**
* 创建部门
*/
@ExcelProperty(value = "创建部门")
private Long createDept;
/**
* 任务组ID
*/
@ExcelProperty(value = "任务组ID")
private Long groupId;
/**
* 列队任务ID
*/
@ExcelProperty(value = "列队任务ID")
private String taskId;
/**
* 审核结果
*/
@ExcelProperty(value = "审核结果")
@ExcelDictFormat(dictType = "review_result")
private String resultType;
/**
* 招标文件oss存储id
*/
@ExcelProperty(value = "招标文件OSS存储ID")
private String tenderDocOssId;
/**
* 投标文件oss存储id
*/
@ExcelProperty(value = "投标文件OSS存储ID")
private String bidDocZipOssId;
/**
* PDF文件路径
*/
@ExcelProperty(value = "PDF文件路径")
private String pdfPath;
/**
* 创建人
*/
@ExcelProperty(value = "创建人")
private Long createBy;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private Date createTime;
/**
* 更新人
*/
@ExcelProperty(value = "更新人")
private Long updateBy;
/**
* 更新时间
*/
@ExcelProperty(value = "更新时间")
private Date updateTime;
}

33
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/enums/TenderReviewStatusEnum.java

@ -0,0 +1,33 @@
package org.dromara.tenderreview.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 招投标审核状态枚举
*
* @author ruoyi
* @date 2024-01-01
*/
@Getter
@AllArgsConstructor
public enum TenderReviewStatusEnum {
PENDING("0", "待审核"),
REVIEWING("1", "审核中"),
PASSED("2", "审核通过"),
REJECTED("3", "审核不通过");
private final String code;
private final String desc;
public static TenderReviewStatusEnum getByCode(String code) {
for (TenderReviewStatusEnum status : values()) {
if (status.getCode().equals(code)) {
return status;
}
}
return null;
}
}

14
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/TenderTaskResultDetailMapper.java

@ -0,0 +1,14 @@
package org.dromara.productManagement.mapper;
import org.dromara.productManagement.domain.TenderTaskResultDetail;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 招投标任务结果详情Mapper接口
*
* @author guoyan
* @date 2024-12-14
*/
public interface TenderTaskResultDetailMapper extends BaseMapperPlus<TenderTaskResultDetail, TenderTaskResultDetail> {
}

16
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/TenderTaskTypeMapper.java

@ -0,0 +1,16 @@
package org.dromara.productManagement.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.productManagement.domain.TenderTaskType;
import org.dromara.productManagement.domain.vo.TenderTaskTypeVo;
/**
* 招投标类型Mapper接口
*
* @author guoyan
* @date 2024-12-14
*/
public interface TenderTaskTypeMapper extends BaseMapperPlus<TenderTaskType, TenderTaskTypeVo> {
}

41
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/mapper/TenderTasksMapper.java

@ -0,0 +1,41 @@
package org.dromara.productManagement.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.productManagement.domain.TenderTaskGroup;
import org.dromara.productManagement.domain.TenderTasks;
import org.dromara.productManagement.domain.vo.TenderTaskResultVO;
import org.dromara.productManagement.domain.vo.TenderTasksVo;
import java.util.List;
/**
* 招投标审核任务Mapper接口
*
* @author ruoyi
* @date 2024-01-01
*/
public interface TenderTasksMapper extends BaseMapperPlus<TenderTasks, TenderTasksVo> {
/**
* 根据任务ID获取详细的文档任务结果
*
* @param taskId 任务ID
* @return 文档任务结果详情列表
*/
List<TenderTaskResultVO> getResultsByTaskId(@Param("taskId") String taskId);
/**
* 分页查询招投标任务分组列表
*
* @param page 分页参数
* @param wrapper 查询条件
* @return 招投标任务分组分页列表
*/
Page<TenderTaskGroup> selectTenderTaskGroups(@Param("page") Page<TenderTasks> page, @Param(Constants.WRAPPER) Wrapper<TenderTasks> wrapper);
}

57
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/ITenderTaskResultsService.java

@ -0,0 +1,57 @@
package org.dromara.productManagement.service;
import org.dromara.productManagement.domain.vo.TenderTaskResultVO;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 招投标任务结果Service接口
*
* @author guoyan
* @date 2024-12-14
*/
public interface ITenderTaskResultsService {
/**
* 根据任务ID查询详细的招投标任务结果
*
* @param taskId 任务ID
* @return 详细的招投标任务结果列表
*/
List<TenderTaskResultVO> getDetailResultsByTaskId(String taskId);
/**
* 下载招投标任务结果
*
* @param ids 主键数组
* @param response HTTP响应对象
*/
void downloadResult(Long[] ids, HttpServletResponse response);
/**
* 获取招投标任务PDF文件流
*
* @param taskId 任务ID
* @param response HTTP响应对象
*/
void getPdfStream(String taskId, HttpServletResponse response);
/**
* 获取招投标文件PDF文件流
*
* @param taskId 任务ID
* @param response HTTP响应对象
*/
void getBidPdfStream(String taskId, HttpServletResponse response);
/**
* 更新招投标任务结果项的状态已读/采纳
*
* @param id 结果项ID
* @param field 字段名isRead/isAdopted
* @param value 0/1
* @return 是否更新成功
*/
Boolean updateResultItemStatus(String id, String field, String value);
}

68
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/ITenderTaskTypeService.java

@ -0,0 +1,68 @@
package org.dromara.productManagement.service;
import org.dromara.productManagement.domain.bo.TenderTaskTypeBo;
import org.dromara.productManagement.domain.vo.TenderTaskTypeVo;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import java.util.Collection;
import java.util.List;
/**
* 招投标类型Service接口
*
* @author guoyan
* @date 2024-12-14
*/
public interface ITenderTaskTypeService {
/**
* 查询招投标类型
*
* @param id 主键
* @return 招投标类型
*/
TenderTaskTypeVo queryById(Long id);
/**
* 分页查询招投标类型列表
*
* @param bo 查询条件
* @param pageQuery 分页参数
* @return 招投标类型分页列表
*/
TableDataInfo<TenderTaskTypeVo> queryPageList(TenderTaskTypeBo bo, PageQuery pageQuery);
/**
* 查询符合条件的招投标类型列表
*
* @param bo 查询条件
* @return 招投标类型列表
*/
List<TenderTaskTypeVo> queryList(TenderTaskTypeBo bo);
/**
* 新增招投标类型
*
* @param bo 招投标类型
* @return 是否新增成功
*/
Boolean insertByBo(TenderTaskTypeBo bo);
/**
* 修改招投标类型
*
* @param bo 招投标类型
* @return 是否修改成功
*/
Boolean updateByBo(TenderTaskTypeBo bo);
/**
* 校验并批量删除招投标类型信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
}

61
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/ITenderTasksService.java

@ -0,0 +1,61 @@
package org.dromara.productManagement.service;
import org.dromara.productManagement.domain.TenderTaskGroup;
import org.dromara.productManagement.domain.vo.TenderTasksVo;
import org.dromara.productManagement.domain.bo.TenderTasksBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
/**
* 招投标审核任务Service接口
*
* @author ruoyi
* @date 2024-01-01
*/
public interface ITenderTasksService {
/**
* 查询招投标审核任务
*/
TenderTasksVo queryById(Long id);
/**
* 查询招投标审核任务列表
*/
TableDataInfo<TenderTasksVo> queryPageList(TenderTasksBo bo, PageQuery pageQuery);
/**
* 分页查询招投标任务分组列表
*/
TableDataInfo<TenderTaskGroup> queryGroupPageList(TenderTasksBo bo, PageQuery pageQuery);
/**
* 查询招投标审核任务列表
*/
List<TenderTasksVo> queryList(TenderTasksBo bo);
/**
* 新增招投标审核任务
*/
Boolean insertByBo(TenderTasksBo bo);
/**
* 修改招投标审核任务
*/
Boolean updateByBo(TenderTasksBo bo);
/**
* 校验并批量删除招投标审核任务信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 删除招投标任务文件
*/
Boolean ossRemoveById(String ossId, Boolean isValid);
}

823
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/TenderTaskResultsServiceImpl.java

@ -0,0 +1,823 @@
package org.dromara.productManagement.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lowagie.text.pdf.BaseFont;
import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.data.MutableDataSet;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.dromara.common.core.service.DictService;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.productManagement.domain.TenderTaskResultDetail;
import org.dromara.productManagement.domain.vo.TenderTaskResultVO;
import org.dromara.productManagement.domain.vo.TenderTasksVo;
import org.dromara.productManagement.mapper.TenderTaskResultDetailMapper;
import org.dromara.productManagement.mapper.TenderTasksMapper;
import org.dromara.productManagement.service.ITenderTaskResultsService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Safelist;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xhtmlrenderer.pdf.ITextRenderer;
import jakarta.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.ArrayList;
/**
* 招投标任务结果Service业务层处理
*
* @author guoyan
* @date 2024-12-14
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class TenderTaskResultsServiceImpl implements ITenderTaskResultsService {
private final TenderTaskResultDetailMapper tenderTaskResultDetailMapper;
private final TenderTasksMapper tenderTasksMapper;
private final DictService dictService;
@Autowired
private DataSource dataSource;
/**
* 根据任务ID查询详细的招投标任务结果
*/
@Override
@DS("slave")
public List<TenderTaskResultVO> getDetailResultsByTaskId(String taskId) {
List<TenderTaskResultVO> originalResults = tenderTasksMapper.getResultsByTaskId(taskId);
// 如果没有结果,直接返回
if (originalResults == null || originalResults.isEmpty()) {
return originalResults;
}
// 为每个原始分类中的结果设置序号
for (TenderTaskResultVO category : originalResults) {
if (category.getResults() != null) {
for (int i = 0; i < category.getResults().size(); i++) {
TenderTaskResultVO.ResultItem item = category.getResults().get(i);
item.setSerialNumber(i + 1);
}
}
}
return originalResults;
}
/**
* 更新招投标任务结果项的状态已读/采纳
*/
@Override
@DS("slave")
public Boolean updateResultItemStatus(String id, String field, String value) {
// 验证字段名是否合法
if (!"isRead".equals(field) && !"isAdopted".equals(field)) {
throw new RuntimeException("不支持更新的字段: " + field);
}
// 验证值是否合法
if (!"0".equals(value) && !"1".equals(value)) {
throw new RuntimeException("无效的值: " + value);
}
try {
LambdaUpdateWrapper<TenderTaskResultDetail> updateWrapper = Wrappers.lambdaUpdate(TenderTaskResultDetail.class);
updateWrapper.eq(TenderTaskResultDetail::getId, id);
if ("isRead".equals(field)) {
updateWrapper.set(TenderTaskResultDetail::getIsRead, value);
} else {
updateWrapper.set(TenderTaskResultDetail::getIsAdopted, value);
}
return tenderTaskResultDetailMapper.update(null, updateWrapper) > 0;
} catch (Exception e) {
throw new RuntimeException("更新状态失败: " + e.getMessage(), e);
}
}
/**
* 下载招投标任务结果
*/
@Override
@DS("slave")
public void downloadResult(Long[] ids, HttpServletResponse response) {
try {
if (ids.length > 0) {
if (ids.length > 1) {
// 多文件压缩下载
String tempDir = System.getProperty("java.io.tmpdir");
String zipFileName = "tender_results_export.zip";
String zipFilePath = tempDir + File.separator + zipFileName;
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFilePath))) {
for (Long taskId : ids) {
TenderTasksVo tenderTasksVo = tenderTasksMapper.selectVoById(taskId);
if (tenderTasksVo == null) continue;
String documentName = tenderTasksVo.getTenderDocumentName();
String taskName = tenderTasksVo.getTaskName();
String taskType = "tender_review";
String label = dictService.getDictLabel(taskType, taskName);
// 获取详细的任务结果
List<TenderTaskResultVO> resultDetails = getDetailResultsByTaskId(String.valueOf(taskId));
if (resultDetails != null && !resultDetails.isEmpty()) {
// 根据任务类型生成Markdown
String markdown = generateTenderMarkdownByTaskTypeAndCategories(taskName, resultDetails);
if (StringUtils.isNotBlank(markdown)) {
// 生成文档标题
String title = "招投标文件分析报告";
String fullMarkdown = String.format("# %s\n\n**文档名称**: %s \n**任务类型**: %s\n\n%s",
title, documentName, label, markdown);
// 转换为PDF
String tempPdfPath = tempDir + File.separator + "tender_result_" + taskId + ".pdf";
convertMarkdownToPdf(fullMarkdown, tempPdfPath);
// 添加到ZIP文件
String pdfFileName = String.format("%s_%s.pdf", documentName, label);
addToZip(tempPdfPath, pdfFileName, zos);
// 删除临时PDF文件
Files.deleteIfExists(new File(tempPdfPath).toPath());
}
}
}
}
// 下载ZIP文件
downloadFile(response, zipFilePath, zipFileName);
// 删除临时ZIP文件
Files.deleteIfExists(new File(zipFilePath).toPath());
} else {
// 单文件PDF下载
Long taskId = ids[0];
TenderTasksVo tenderTasksVo = tenderTasksMapper.selectVoById(taskId);
if (tenderTasksVo == null) {
throw new RuntimeException("任务不存在");
}
String documentName = tenderTasksVo.getBidDocumentName();
String taskName = tenderTasksVo.getTaskName();
String taskType = "tender_review";
String label = dictService.getDictLabel(taskType, taskName);
// 获取详细的任务结果
List<TenderTaskResultVO> resultDetails = getDetailResultsByTaskId(String.valueOf(taskId));
if (resultDetails != null && !resultDetails.isEmpty()) {
// 根据任务类型生成Markdown
String markdown = generateTenderMarkdownByTaskTypeAndCategories(taskName, resultDetails);
if (StringUtils.isNotBlank(markdown)) {
// 生成文档标题
String title = "招投标文件分析报告";
String fullMarkdown = String.format("# %s\n\n**文档名称**: %s \n**任务类型**: %s\n\n%s",
title, documentName, label, markdown);
// 转换为PDF
String tempDir = System.getProperty("java.io.tmpdir");
String tempPdfPath = tempDir + File.separator + "tender_result_" + taskId + ".pdf";
convertMarkdownToPdf(fullMarkdown, tempPdfPath);
// 下载文件
String fileName = String.format("%s_%s.pdf", documentName, label);
downloadFile(response, tempPdfPath, fileName);
// 删除临时文件
Files.deleteIfExists(new File(tempPdfPath).toPath());
}
}
}
}
} catch (Exception e) {
log.error("下载结果失败", e);
throw new RuntimeException("下载结果失败: " + e.getMessage());
}
}
/**
* 获取招投标任务PDF文件流
*/
/**
* 获取招投标任务PDF文件流
*/
@Override
@DS("slave")
public void getPdfStream(String taskId, HttpServletResponse response) {
try {
// 查询任务信息
TenderTasksVo task = tenderTasksMapper.selectVoById(Long.valueOf(taskId));
if (task == null) {
throw new RuntimeException("任务不存在");
}
String pdfPath = task.getPdfPath();
String filePath = "";
if (StringUtils.isNotEmpty(pdfPath)) {
// 如果pdfPath存在,直接使用该路径
filePath = pdfPath;
} else {
throw new RuntimeException("文件信息不存在");
}
log.info("开始输出招投标PDF文件: " + filePath);
// 读取文件并输出到response
File file = new File(filePath);
if (!file.exists()) {
throw new RuntimeException("PDF文件不存在: " + filePath);
}
log.info("招投标PDF文件存在,开始输出: " + filePath);
// // 使用JDBC更新数据库
// try (Connection conn = dataSource.getConnection()) {
// String sql = "UPDATE tender_tasks SET pdf_path = ? WHERE id = ?";
// try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
// pstmt.setString(1, filePath);
// pstmt.setLong(2, Long.parseLong(taskId));
// pstmt.executeUpdate();
// }
// } catch (SQLException e) {
// log.error("更新招投标PDF路径失败", e);
// throw new RuntimeException("更新招投标PDF路径失败: " + e.getMessage());
// }
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getName(), StandardCharsets.UTF_8.name()));
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis, 8192);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.flush();
}
} catch (Exception e) {
log.error("获取招投标PDF文件流失败", e);
throw new RuntimeException("获取招投标PDF文件流失败: " + e.getMessage());
}
}
/**
* 获取招投标文件PDF文件流
*/
@Override
@DS("slave")
public void getBidPdfStream(String taskId, HttpServletResponse response) {
try {
// 设置响应头
response.setContentType("application/pdf");
response.setHeader("Content-Disposition",
"attachment; filename=tender_bid_document_" + taskId + ".pdf");
// 这里需要实现具体的招投标文件PDF获取逻辑
// 目前先返回一个简单的提示
response.getWriter().write("招投标文件PDF获取功能待实现");
} catch (Exception e) {
throw new RuntimeException("获取招投标文件PDF失败", e);
}
}
/**
* 根据任务类型和分类生成Markdown内容统一使用多tabs模式
*
* @param taskName 任务类型名称
* @param resultDetails 结果详情列表
* @return Markdown内容
*/
private String generateTenderMarkdownByTaskTypeAndCategories(String taskName, List<TenderTaskResultVO> resultDetails) {
// 统一使用多tabs模式,根据任务类型获取tabs配置
return generateTenderMarkdownByTabsConfig(taskName, resultDetails);
}
/**
* 根据任务类型的tabs配置生成Markdown内容
*
* @param taskName 任务类型名称
* @param resultDetails 结果详情列表
* @return Markdown内容
*/
private String generateTenderMarkdownByTabsConfig(String taskName, List<TenderTaskResultVO> resultDetails) {
StringBuilder markdown = new StringBuilder();
// 获取任务类型对应的tabs配置
List<TenderTabConfig> tabConfigs = getTenderTabConfigsByTaskType(taskName);
log.info("任务类型: {}, 配置的tabs数量: {}", taskName, tabConfigs.size());
// 记录可用的分类名称
List<String> availableCategories = resultDetails.stream()
.map(TenderTaskResultVO::getName)
.collect(java.util.stream.Collectors.toList());
log.info("可用的分类名称: {}", availableCategories);
// 按照tabs配置的顺序处理每个tab
for (TenderTabConfig tabConfig : tabConfigs) {
String tabName = tabConfig.getTabName();
log.info("处理tab: {}, 字段配置数量: {}", tabName, tabConfig.getFieldConfigs().size());
// 查找对应的分类数据
TenderTaskResultVO matchingCategory = null;
for (TenderTaskResultVO category : resultDetails) {
if (tabName.equals(category.getName())) {
matchingCategory = category;
break;
}
}
// 如果找到对应的分类数据,添加到markdown中
if (matchingCategory != null && matchingCategory.getResults() != null && !matchingCategory.getResults().isEmpty()) {
log.info("找到匹配的分类数据: {}, 结果数量: {}", tabName, matchingCategory.getResults().size());
// 添加分类标题
markdown.append("## ").append(tabName).append("\n\n");
// 处理该分类下的每个结果项
for (TenderTaskResultVO.ResultItem item : matchingCategory.getResults()) {
markdown.append("### ").append(item.getSerialNumber()).append(". ").append(item.getExistingIssues()).append("\n\n");
// 根据tab配置显示各字段内容
for (TenderFieldConfig fieldConfig : tabConfig.getFieldConfigs()) {
String fieldValue = getTenderFieldValueWithJsonSupport(item, fieldConfig.getField());
if (StringUtils.isNotBlank(fieldValue)) {
markdown.append("**").append(fieldConfig.getTitle()).append("**\n\n").append(fieldValue).append("\n\n");
}
}
// 添加分隔线
markdown.append("---\n\n");
}
} else {
log.warn("未找到匹配的分类数据: {}", tabName);
}
}
return markdown.toString();
}
/**
* 根据任务类型获取对应的tabs配置
*
* @param taskName 任务类型名称
* @return tabs配置列表
*/
private List<TenderTabConfig> getTenderTabConfigsByTaskType(String taskName) {
List<TenderTabConfig> configs = new ArrayList<>();
// 根据任务类型返回不同的tabs配置
switch (taskName) {
case "bidConsistencyReview":
// 投标一致性审查 - 4个tabs
configs.add(new TenderTabConfig("文档元数据", Arrays.asList(
new TenderFieldConfig("reviewBasis.review_points", "元数据要点")
)));
configs.add(new TenderTabConfig("重点关注相似内容", Arrays.asList(
new TenderFieldConfig("modificationDisplay", "各文档具体内容"),
new TenderFieldConfig("reviewBasis.error_review_points", "错别字")
)));
// configs.add(new TenderTabConfig("错别字", Arrays.asList(
// new TenderFieldConfig("reviewBasis.error_review_points", "错别字详情"),
// new TenderFieldConfig("modificationDisplay", "修改情况")
// )));
configs.add(new TenderTabConfig("一般相似内容", Arrays.asList(
new TenderFieldConfig("reviewBasis.review_points", "各文档具体内容")
)));
break;
case "tenderComplianceReview":
// 招投标合规性审查
configs.add(new TenderTabConfig("合规性检查", Arrays.asList(
new TenderFieldConfig("originalText", "原文"),
new TenderFieldConfig("reviewBasis.review_content", "审查意见"),
new TenderFieldConfig("reviewBasis.review_points", "审查要点"),
new TenderFieldConfig("modificationDisplay", "修改情况")
)));
break;
case "bidDocumentAnalysis":
// 投标文档分析
configs.add(new TenderTabConfig("文档分析", Arrays.asList(
new TenderFieldConfig("originalText", "原文"),
new TenderFieldConfig("comparedText", "比对原文"),
new TenderFieldConfig("reviewBasis.review_content", "分析结果"),
new TenderFieldConfig("modificationDisplay", "修改建议")
)));
break;
case "tenderDocumentCheck":
// 招标文档检查
configs.add(new TenderTabConfig("文档检查", Arrays.asList(
new TenderFieldConfig("originalText", "原文"),
new TenderFieldConfig("reviewBasis.review_points", "检查要点"),
new TenderFieldConfig("modifiedContent", "修改建议"),
new TenderFieldConfig("modificationDisplay", "修改情况")
)));
break;
case "contractComplianceReview":
// 合同合规性审查
configs.add(new TenderTabConfig("合同审查", Arrays.asList(
new TenderFieldConfig("originalText", "原文"),
new TenderFieldConfig("reviewBasis.review_content", "审查意见"),
new TenderFieldConfig("reviewBasis.review_points", "审查要点"),
new TenderFieldConfig("modificationDisplay", "修改情况")
)));
break;
default:
// 默认配置 - 使用通用的4个tabs结构
configs.add(new TenderTabConfig("文档元数据", Arrays.asList(
new TenderFieldConfig("reviewBasis.review_points", "元数据要点")
)));
configs.add(new TenderTabConfig("重点关注相似内容", Arrays.asList(
new TenderFieldConfig("modificationDisplay", "各文档具体内容"),
new TenderFieldConfig("reviewBasis.error_review_points", "错别字")
)));
configs.add(new TenderTabConfig("错别字", Arrays.asList(
new TenderFieldConfig("reviewBasis.error_review_points", "错别字详情"),
new TenderFieldConfig("modificationDisplay", "修改情况")
)));
configs.add(new TenderTabConfig("一般相似内容", Arrays.asList(
new TenderFieldConfig("modificationDisplay", "各文档具体内容")
)));
break;
}
return configs;
}
/**
* 获取结果项对象的字段值支持从reviewBasis JSON中提取数据
*
* @param item 结果项对象
* @param fieldName 字段名支持嵌套字段 reviewBasis.reviewContent
* @return 字段值
*/
private String getTenderFieldValueWithJsonSupport(TenderTaskResultVO.ResultItem item, String fieldName) {
try {
// 处理嵌套字段,如 reviewBasis.reviewContent
if (fieldName.contains(".")) {
String[] parts = fieldName.split("\\.", 2);
String mainField = parts[0];
String subField = parts[1];
// 获取主字段值
Object mainValue = getFieldValueByReflection(item, mainField);
if (mainValue == null) {
return "";
}
// 如果主字段是JSON字符串,解析并提取子字段
if (mainValue instanceof String && "reviewBasis".equals(mainField)) {
try {
// 使用简单的JSON解析方式
String jsonStr = (String) mainValue;
return extractJsonField(jsonStr, subField);
} catch (Exception e) {
log.error("解析JSON字段失败: {}, {}", fieldName, e.getMessage());
return "";
}
}
}
// 处理普通字段
Object value = getFieldValueByReflection(item, fieldName);
if (value != null) {
String stringValue = value.toString();
// 对于普通字段也处理<br>标签
return stringValue
.replace("<br>", "\n\n")
.replace("<br/>", "\n\n")
.replace("<BR>", "\n\n")
.replace("<BR/>", "\n\n");
}
return "";
} catch (Exception e) {
log.error("获取字段值失败: {}, {}", fieldName, e.getMessage());
return "";
}
}
/**
* 通过反射获取字段值
*/
private Object getFieldValueByReflection(TenderTaskResultVO.ResultItem item, String fieldName) throws Exception {
java.lang.reflect.Method method = item.getClass().getMethod("get" + StringUtils.capitalize(fieldName));
return method.invoke(item);
}
/**
* 从JSON字符串中提取指定字段的值
*/
private String extractJsonField(String jsonStr, String fieldName) {
if (StringUtils.isBlank(jsonStr) || StringUtils.isBlank(fieldName)) {
return "";
}
try {
// 支持前端配置中的各种字段
switch (fieldName) {
case "reviewContent":
case "review_content":
return extractStringField(jsonStr, fieldName);
case "reviewPoints":
case "review_points":
case "error_review_points":
return extractArrayField(jsonStr, fieldName, "\n\n• ");
default:
// 尝试作为字符串字段提取
String stringResult = extractStringField(jsonStr, fieldName);
if (StringUtils.isNotBlank(stringResult)) {
return stringResult;
}
// 尝试作为数组字段提取
return extractArrayField(jsonStr, fieldName, "\n\n• ");
}
} catch (Exception e) {
log.error("提取JSON字段失败: {}, {}", fieldName, e.getMessage());
return "";
}
}
/**
* 从JSON中提取字符串字段
*/
private String extractStringField(String jsonStr, String fieldName) {
int start = jsonStr.indexOf("\"" + fieldName + "\"");
if (start == -1) return "";
start = jsonStr.indexOf(":", start) + 1;
start = jsonStr.indexOf("\"", start) + 1;
int end = jsonStr.indexOf("\"", start);
if (start > 0 && end > start) {
return jsonStr.substring(start, end)
.replace("\\n", "\n")
.replace("\\\"", "\"")
.replace("\\\\", "\\")
.replace("\\t", "\t")
.replace("<br>", "\n\n")
.replace("<br/>", "\n\n")
.replace("<BR>", "\n\n")
.replace("<BR/>", "\n\n");
}
return "";
}
/**
* 从JSON中提取数组字段并格式化
*/
private String extractArrayField(String jsonStr, String fieldName, String prefix) {
int start = jsonStr.indexOf("\"" + fieldName + "\"");
if (start == -1) return "";
start = jsonStr.indexOf("[", start);
int end = jsonStr.indexOf("]", start) + 1;
if (start > 0 && end > start) {
String arrayStr = jsonStr.substring(start, end);
// 处理数组,提取字符串元素
String result = arrayStr.replaceAll("\\[|\\]", "")
.replaceAll("\"\\s*,\\s*\"", "\",\"");
if (StringUtils.isNotBlank(result)) {
String[] elements = result.split("\",\"");
StringBuilder formatted = new StringBuilder();
for (String element : elements) {
String cleanElement = element.replaceAll("^\"|\"$", "")
.replace("\\n", "\n")
.replace("\\\"", "\"")
.replace("\\\\", "\\")
.replace("\\t", "\t")
.replace("<br>", "\n\n")
.replace("<br/>", "\n\n")
.replace("<BR>", "\n\n")
.replace("<BR/>", "\n\n");
if (StringUtils.isNotBlank(cleanElement)) {
if (formatted.length() > 0) {
formatted.append(prefix);
} else {
formatted.append("• ");
}
formatted.append(cleanElement);
}
}
return formatted.toString();
}
}
return "";
}
/**
* Markdown转PDF方法
*/
private void convertMarkdownToPdf(String markdown, String outputPath) throws Exception {
MutableDataSet options = new MutableDataSet();
options.set(Parser.EXTENSIONS, Arrays.asList(
TablesExtension.create(),
StrikethroughExtension.create()
));
Parser parser = Parser.builder(options).build();
HtmlRenderer renderer = HtmlRenderer.builder(options)
.extensions(Arrays.asList(
TablesExtension.create(),
StrikethroughExtension.create()
))
.build();
Node document = parser.parse(markdown);
String htmlContent = renderer.render(document);
// 使用 JSoup 清理
Document.OutputSettings settings = new Document.OutputSettings();
settings.prettyPrint(false);
Safelist safelist = Safelist.relaxed()
.addTags("em", "strong", "div", "span", "br", "table", "thead", "tbody", "tr", "th", "td", "font")
.addAttributes(":all", "style", "class", "color")
.addAttributes("table", "border", "cellpadding", "cellspacing")
.addAttributes("font", "color");
htmlContent = Jsoup.clean(htmlContent, "", safelist, settings);
// 创建完整的HTML文档
String html = String.format("""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<style type="text/css">
body {
font-family: Microsoft YaHei, SimSun, Arial;
line-height: 1.6;
margin: 20px;
font-size: 14px;
}
p { margin: 10px 0; }
pre {
background-color: #f5f5f5;
padding: 10px;
border-radius: 4px;
}
table {
border-collapse: collapse;
width: 100%%;
margin: 10px 0;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f5f5f5;
font-weight: bold;
}
.highlight {
background-color: #ffff00;
}
font[color=red] {
color: red;
font-weight: bold;
}
</style>
</head>
<body>
%s
</body>
</html>
""", htmlContent.replace("<br>", "\n"));
// 配置Flying Saucer
ITextRenderer pdfRenderer = new ITextRenderer();
// 加载字体
try (InputStream is = getClass().getResourceAsStream("/fonts/msyh.ttc")) {
if (is != null) {
File tempFont = File.createTempFile("msyh", ".ttc");
FileUtils.copyInputStreamToFile(is, tempFont);
pdfRenderer.getFontResolver().addFont(tempFont.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
tempFont.deleteOnExit();
}
} catch (Exception e) {
log.warn("加载字体失败,使用默认字体: {}", e.getMessage());
}
pdfRenderer.setDocumentFromString(html);
pdfRenderer.getSharedContext().setBaseURL("file:///");
pdfRenderer.layout();
try (OutputStream os = new FileOutputStream(outputPath)) {
pdfRenderer.createPDF(os, true);
}
}
/**
* 添加文件到ZIP
*/
private void addToZip(String filePath, String fileName, ZipOutputStream zos) throws IOException {
byte[] buffer = new byte[1024];
try (FileInputStream fis = new FileInputStream(filePath)) {
zos.putNextEntry(new ZipEntry(fileName));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
}
}
/**
* 文件下载方法
*/
private void downloadFile(HttpServletResponse response, String filePath, String fileName) throws IOException {
File file = new File(filePath);
if (!file.exists()) {
throw new RuntimeException("文件不存在");
}
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" +
URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()));
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int i;
while ((i = bis.read(buffer)) != -1) {
os.write(buffer, 0, i);
}
}
}
/**
* 招投标任务字段配置类
*/
private static class TenderFieldConfig {
private String field;
private String title;
public TenderFieldConfig(String field, String title) {
this.field = field;
this.title = title;
}
public String getField() {
return field;
}
public String getTitle() {
return title;
}
}
/**
* 招投标任务tabs配置类
*/
private static class TenderTabConfig {
private String tabName;
private List<TenderFieldConfig> fieldConfigs;
public TenderTabConfig(String tabName, List<TenderFieldConfig> fieldConfigs) {
this.tabName = tabName;
this.fieldConfigs = fieldConfigs;
}
public String getTabName() {
return tabName;
}
public List<TenderFieldConfig> getFieldConfigs() {
return fieldConfigs;
}
}
}

144
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/TenderTaskTypeServiceImpl.java

@ -0,0 +1,144 @@
package org.dromara.productManagement.service.impl;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.productManagement.service.ITenderTaskTypeService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.dromara.productManagement.domain.bo.TenderTaskTypeBo;
import org.dromara.productManagement.domain.vo.TenderTaskTypeVo;
import org.dromara.productManagement.domain.TenderTaskType;
import org.dromara.productManagement.mapper.TenderTaskTypeMapper;
import java.util.List;
import java.util.Collection;
import java.util.Map;
/**
* 招投标类型Service业务层处理
*
* @author guoyan
* @date 2024-12-14
*/
@RequiredArgsConstructor
@Service
@Transactional
public class TenderTaskTypeServiceImpl implements ITenderTaskTypeService {
private final TenderTaskTypeMapper baseMapper;
/**
* 查询招投标类型
*
* @param id 招投标类型主键
* @return 招投标类型
*/
@Override
public TenderTaskTypeVo queryById(Long id) {
return baseMapper.selectVoById(id);
}
/**
* 查询招投标类型列表
*
* @param bo 招投标类型
* @return 招投标类型
*/
@Override
public TableDataInfo<TenderTaskTypeVo> queryPageList(TenderTaskTypeBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TenderTaskType> lqw = buildQueryWrapper(bo);
Page<TenderTaskTypeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 查询招投标类型列表
*
* @param bo 招投标类型
* @return 招投标类型
*/
@Override
public List<TenderTaskTypeVo> queryList(TenderTaskTypeBo bo) {
LambdaQueryWrapper<TenderTaskType> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<TenderTaskType> buildQueryWrapper(TenderTaskTypeBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TenderTaskType> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getTenderName()), TenderTaskType::getTenderName, bo.getTenderName());
lqw.eq(bo.getSort() != null, TenderTaskType::getSort, bo.getSort());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), TenderTaskType::getStatus, bo.getStatus());
return lqw;
}
/**
* 新增招投标类型
*
* @param bo 招投标类型
* @return 结果
*/
@Override
public Boolean insertByBo(TenderTaskTypeBo bo) {
TenderTaskType add = MapstructUtils.convert(bo, TenderTaskType.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
}
return flag;
}
/**
* 修改招投标类型
*
* @param bo 招投标类型
* @return 结果
*/
@Override
public Boolean updateByBo(TenderTaskTypeBo bo) {
TenderTaskType update = MapstructUtils.convert(bo, TenderTaskType.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*
* @param entity 实体类数据
*/
private void validEntityBeforeSave(TenderTaskType entity) {
// 校验招投标类型名称是否重复
if (StringUtils.isNotEmpty(entity.getTenderName())) {
LambdaQueryWrapper<TenderTaskType> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(TenderTaskType::getTenderName, entity.getTenderName());
if (entity.getId() != null) {
queryWrapper.ne(TenderTaskType::getId, entity.getId());
}
if (baseMapper.selectCount(queryWrapper) > 0) {
throw new RuntimeException("招投标类型名称已存在");
}
}
}
/**
* 批量删除招投标类型
*
* @param ids 需要删除的招投标类型主键
* @return 结果
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if (isValid) {
// 校验是否存在关联的招投标任务
// 这里可以添加业务校验逻辑
}
return baseMapper.deleteBatchIds(ids) > 0;
}
}

347
zaojiaManagement/zaojia-productManagement/src/main/java/org/dromara/productManagement/service/impl/TenderTasksServiceImpl.java

@ -0,0 +1,347 @@
package org.dromara.productManagement.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import okhttp3.*;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.productManagement.service.ITenderTasksService;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.dromara.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.productManagement.domain.TenderTaskGroup;
import org.dromara.productManagement.domain.bo.TenderTasksBo;
import org.dromara.productManagement.domain.vo.TenderTasksVo;
import org.dromara.productManagement.domain.TenderTasks;
import org.dromara.productManagement.mapper.TenderTasksMapper;
import jakarta.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
/**
* 招投标审核任务Service业务层处理
*
* @author ruoyi
* @date 2024-01-01
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class TenderTasksServiceImpl implements ITenderTasksService {
private final TenderTasksMapper baseMapper;
protected final ISysOssService ossService;
protected final ISysUserService userService;
@Value("${chat.chatUrl}")
private String backTaskUrl;
@Autowired
private DataSource dataSource;
/**
* 查询招投标审核任务
*/
@Override
public TenderTasksVo queryById(Long id){
return baseMapper.selectVoById(id);
}
/**
* 查询招投标审核任务列表
*/
@Override
@DS("slave")
public TableDataInfo<TenderTasksVo> queryPageList(TenderTasksBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TenderTasks> lqw = buildQueryWrapper(bo);
Page<TenderTasksVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
/**
* 分页查询招投标任务分组列表
*/
@Override
@DS("slave")
public TableDataInfo<TenderTaskGroup> queryGroupPageList(TenderTasksBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<TenderTasks> lqw = buildGroupQueryWrapper(bo);
Page<TenderTaskGroup> tenderTaskGroupPage = baseMapper.selectTenderTaskGroups(pageQuery.build(), lqw);
tenderTaskGroupPage.getRecords().forEach(vo -> {
Long createBy = vo.getCreateBy();
// 切换到主库查询用户信息
DynamicDataSourceContextHolder.push("master");
try {
vo.setCreateUser(userService.selectUserById(createBy).getNickName());
} finally {
// 确保在finally块中恢复数据源,防止异常导致数据源未切回
DynamicDataSourceContextHolder.poll();
}
});
return TableDataInfo.build(tenderTaskGroupPage);
}
/**
* 查询招投标审核任务列表
*/
@Override
public List<TenderTasksVo> queryList(TenderTasksBo bo) {
LambdaQueryWrapper<TenderTasks> lqw = buildQueryWrapper(bo);
return baseMapper.selectVoList(lqw);
}
private LambdaQueryWrapper<TenderTasks> buildQueryWrapper(TenderTasksBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TenderTasks> lqw = Wrappers.lambdaQuery();
lqw.like(StringUtils.isNotBlank(bo.getTaskName()), TenderTasks::getTaskName, bo.getTaskName());
lqw.like(StringUtils.isNotBlank(bo.getTenderDocumentName()), TenderTasks::getTenderDocumentName, bo.getTenderDocumentName());
lqw.like(StringUtils.isNotBlank(bo.getBidDocumentName()), TenderTasks::getBidDocumentName, bo.getBidDocumentName());
lqw.eq(StringUtils.isNotBlank(bo.getProgressStatus()), TenderTasks::getProgressStatus, bo.getProgressStatus());
lqw.eq(StringUtils.isNotBlank(bo.getResultType()), TenderTasks::getResultType, bo.getResultType());
lqw.orderByDesc(TenderTasks::getCreateTime);
return lqw;
}
private LambdaQueryWrapper<TenderTasks> buildGroupQueryWrapper(TenderTasksBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<TenderTasks> lqw = Wrappers.lambdaQuery();
// 处理 taskNameList 是 List<String> 的情况
List<String> taskNames = bo.getTaskNameList();
if (taskNames != null && !taskNames.isEmpty()) {
lqw.in(TenderTasks::getTaskName, taskNames);
}
lqw.like(StringUtils.isNotBlank(bo.getTaskName()), TenderTasks::getTaskName, bo.getTaskName());
lqw.like(StringUtils.isNotBlank(bo.getTenderDocumentName()), TenderTasks::getTenderDocumentName, bo.getTenderDocumentName());
lqw.like(StringUtils.isNotBlank(bo.getBidDocumentName()), TenderTasks::getBidDocumentName, bo.getBidDocumentName());
lqw.eq(StringUtils.isNotBlank(bo.getProgressStatus()), TenderTasks::getProgressStatus, bo.getProgressStatus());
lqw.eq(StringUtils.isNotBlank(bo.getResultType()), TenderTasks::getResultType, bo.getResultType());
lqw.orderByDesc(TenderTasks::getCreateTime);
if (!StpUtil.hasRole("superadmin")) {
lqw.eq(TenderTasks::getCreateBy, LoginHelper.getUserId());
}
//分组,作为父项(按文件名分组而不是任务名)
lqw.groupBy(TenderTasks::getCreateBy,
TenderTasks::getTenderDocumentName,
TenderTasks::getBidDocumentName,
TenderTasks::getCreateTime,
TenderTasks::getDeleteFlag);
return lqw;
}
/**
* 新增招投标审核任务
*/
@Override
@DS("slave")
public Boolean insertByBo(TenderTasksBo bo) {
List<String> taskNameList = bo.getTaskNameList();
String bidDocOssId = bo.getBidDocZipOssId();
String tenderDocOssId = bo.getTenderDocOssId();
String bidDocUrl = "";
String bidDocFileName = "";
String tenderDocUrl = "";
String tenderFileName = "";
// 切换到主库查询OSS信息
DynamicDataSourceContextHolder.push("master");
try {
if (bidDocOssId==null && tenderDocOssId==null){
throw new RuntimeException("请上传投标文件或者招标文件");
}
if (bidDocOssId!=null ){
SysOssVo bidDocFiles = ossService.getById(Long.valueOf(bidDocOssId));
if (bidDocFiles!=null) {
bidDocUrl = bidDocFiles.getUrl();
bidDocFileName = bidDocFiles.getOriginalName();
}
}
if (tenderDocOssId!=null ){
SysOssVo tenderDocFiles = ossService.getById(Long.valueOf(tenderDocOssId));
if (tenderDocFiles!=null) {
tenderDocUrl = tenderDocFiles.getUrl();
tenderFileName = tenderDocFiles.getOriginalName();
}
}
} finally {
// 确保在finally块中恢复数据源,防止异常导致数据源未切回
DynamicDataSourceContextHolder.poll();
}
if(bidDocOssId==null && tenderDocOssId==null){
throw new RuntimeException("请上传投标文件或者招标文件");
}
if (taskNameList != null && !taskNameList.isEmpty()) {
for (String taskName : taskNameList) {
// 创建 TenderTasks 实体并设置属性
TenderTasks add = MapstructUtils.convert(bo, TenderTasks.class);
add.setTaskName(taskName);
add.setBidDocumentName(bidDocFileName);
add.setTenderDocumentName(tenderFileName);
add.setProgressStatus("PENDING");
// 验证实体并保存
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
// 发起请求
OkHttpClient client = new OkHttpClient.Builder().build();
HttpUrl.Builder urlBuilder = HttpUrl.parse(backTaskUrl + "/back/taskStart").newBuilder();
urlBuilder.addQueryParameter("userId", String.valueOf(LoginHelper.getUserId()));
urlBuilder.addQueryParameter("taskId", String.valueOf(add.getId()));
urlBuilder.addQueryParameter("filename", bidDocUrl + "\n" + tenderDocUrl);
urlBuilder.addQueryParameter("taskName", taskName);
urlBuilder.addQueryParameter("priority", "1");
Request request = new Request.Builder()
.url(urlBuilder.build())
.build();
// 使用异步调用
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace(); // 处理请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 忽略返回内容
response.close(); // 确保响应被关闭
}
});
} else {
throw new RuntimeException("新增招投标审核任务失败");
}
}
}
return true;
}
/**
* 修改招投标审核任务
*/
@Override
public Boolean updateByBo(TenderTasksBo bo) {
TenderTasks update = MapstructUtils.convert(bo, TenderTasks.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(TenderTasks entity){
// 可以在此处添加业务校验逻辑
}
/**
* 批量删除招投标审核任务
*/
@Override
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
if(isValid){
// 做一些业务上的校验,判断是否需要校验
}
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 删除招投标任务文件
*/
@Override
@DS("slave")
public Boolean ossRemoveById(String ossId, Boolean isValid) {
try {
log.info("开始删除招投标任务文件,ossId: {}", ossId);
// 查找包含该ossId的招投标任务(从库查询)
LambdaQueryWrapper<TenderTasks> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TenderTasks::getTenderDocOssId, ossId)
.or()
.eq(TenderTasks::getBidDocZipOssId, ossId);
List<TenderTasksVo> tasks = baseMapper.selectVoList(queryWrapper);
if (tasks.isEmpty()) {
log.warn("未找到包含ossId: {} 的招投标任务", ossId);
return false;
}
// 切换到主库进行删除和更新操作
DynamicDataSourceContextHolder.push("master");
try {
// 删除文件服务中的文件
ossService.deleteWithValidByIds(Collections.singletonList(Long.valueOf(ossId)), true);
log.info("已删除文件服务中的文件,ossId: {}", ossId);
// 对于找到的每个任务,需要检查并删除相关的其他文件
for (TenderTasksVo task : tasks) {
String tenderDocOssId = task.getTenderDocOssId();
String bidDocZipOssId = task.getBidDocZipOssId();
// 如果删除的是招标文件,还需要删除投标文件(如果有的话)
if (ossId.equals(tenderDocOssId) && StringUtils.isNotBlank(bidDocZipOssId)) {
try {
ossService.deleteWithValidByIds(Collections.singletonList(Long.valueOf(bidDocZipOssId)), true);
log.info("已删除关联的投标文件,ossId: {}", bidDocZipOssId);
} catch (Exception e) {
log.warn("删除关联投标文件失败,ossId: {}, 错误: {}", bidDocZipOssId, e.getMessage());
}
}
// 如果删除的是投标文件,还需要删除招标文件(如果有的话)
if (ossId.equals(bidDocZipOssId) && StringUtils.isNotBlank(tenderDocOssId)) {
try {
ossService.deleteWithValidByIds(Collections.singletonList(Long.valueOf(tenderDocOssId)), true);
log.info("已删除关联的招标文件,ossId: {}", tenderDocOssId);
} catch (Exception e) {
log.warn("删除关联招标文件失败,ossId: {}, 错误: {}", tenderDocOssId, e.getMessage());
}
}
}
} finally {
// 确保在finally块中恢复数据源,防止异常导致数据源未切回
DynamicDataSourceContextHolder.poll();
}
// 更新数据库中的deleteFlag字段
LambdaUpdateWrapper<TenderTasks> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(TenderTasks::getTenderDocOssId, ossId)
.or()
.eq(TenderTasks::getBidDocZipOssId, ossId);
updateWrapper.set(TenderTasks::getDeleteFlag, "Y");
int updateCount = baseMapper.update(null, updateWrapper);
log.info("已更新数据库deleteFlag字段,影响行数: {}", updateCount);
return true;
} catch (Exception e) {
log.error("删除招投标任务文件失败,ossId: {}, 错误: {}", ossId, e.getMessage(), e);
throw new RuntimeException("删除招投标任务文件失败: " + e.getMessage());
}
}
}

7
zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/TenderTaskResultDetailMapper.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.productManagement.mapper.TenderTaskResultDetailMapper">
</mapper>

140
zaojiaManagement/zaojia-productManagement/src/main/resources/mapper/productManagement/TenderTasksMapper.xml

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.productManagement.mapper.TenderTasksMapper">
<resultMap id="TenderTaskGroupResult" type="org.dromara.productManagement.domain.TenderTaskGroup">
<id property="id" column="group_id"/>
<result property="createBy" column="create_by"/>
<result property="tenderDocumentName" column="tender_document_name"/>
<result property="bidDocumentName" column="bid_document_name"/>
<result property="createTime" column="group_create_time"/>
<result property="progress" column="progress"/>
<result property="deleteFlag" column="delete_flag"/>
<!-- 使用collection标签正确映射子任务列表 -->
<collection property="childrenTasks"
column="{createBy=create_by,
tenderDocumentName=tender_document_name,
bidDocumentName=bid_document_name,
groupDate=group_create_time}"
select="selectChildTasks"/>
</resultMap>
<!-- 父级查询 -->
<select id="selectTenderTaskGroups" resultMap="TenderTaskGroupResult">
SELECT
UUID() as group_id,
create_by,
tender_document_name,
bid_document_name,
create_time as group_create_time,
delete_flag,
CASE
WHEN (SUM(CASE WHEN progress_status IN ('SUCCESS', 'FAILURE') THEN 1 ELSE 0 END) * 100.0) / COUNT(*) = 100
THEN
CASE
WHEN SUM(CASE WHEN progress_status = 'FAILURE' THEN 1 ELSE 0 END) > 0
THEN CONCAT(
'100%(',
COUNT(*),
'/',
COUNT(*),
',失败:',
SUM(CASE WHEN progress_status = 'FAILURE' THEN 1 ELSE 0 END),
')'
)
ELSE CONCAT('100%(', COUNT(*), '/', COUNT(*), ')')
END
ELSE
CONCAT(
FLOOR((SUM(CASE WHEN progress_status IN ('SUCCESS', 'FAILURE') THEN 1 ELSE 0 END) * 100.0) / COUNT(*)),
'%(',
SUM(CASE WHEN progress_status IN ('SUCCESS', 'FAILURE') THEN 1 ELSE 0 END),
'/',
COUNT(*),
')'
)
END as progress
FROM tender_tasks
${ew.getCustomSqlSegment}
</select>
<!-- 子任务查询 -->
<select id="selectChildTasks" resultType="org.dromara.productManagement.domain.TenderTaskChild">
SELECT
id,
task_name,
tender_document_name,
bid_document_name,
progress_status,
group_id,
task_id,
result_type,
tender_doc_oss_id,
bid_doc_zip_oss_id,
version,
create_time,
update_time,
CASE
WHEN update_time IS NOT NULL THEN
CASE
WHEN TIMESTAMPDIFF(HOUR, create_time, update_time) >= 1 THEN
CONCAT(
FLOOR(TIMESTAMPDIFF(MINUTE, create_time, update_time) / 60),
'小时',
MOD(TIMESTAMPDIFF(MINUTE, create_time, update_time), 60),
'分钟'
)
ELSE
CONCAT(
TIMESTAMPDIFF(MINUTE, create_time, update_time),
'分钟'
)
END
ELSE NULL
END as task_duration
FROM tender_tasks
WHERE del_flag = '0'
AND create_by = #{createBy}
AND tender_document_name = #{tenderDocumentName}
AND bid_document_name = #{bidDocumentName}
AND create_time = #{groupDate}
ORDER BY create_time DESC
</select>
<resultMap type="org.dromara.productManagement.domain.vo.TenderTaskResultVO$ResultItem" id="TenderTaskResult">
<result property="id" column="id"/>
<result property="serialNumber" column="serial_number"/>
<result property="issueName" column="issue_name"/>
<result property="originalText" column="original_text"/>
<result property="comparedText" column="compared_text"/>
<result property="modifiedContent" column="modified_content"/>
<result property="modificationDisplay" column="modification_display"/>
<result property="existingIssues" column="existing_issues"/>
<result property="reviewBasis" column="review_basis"/>
<result property="isRead" column="is_read"/>
<result property="isAdopted" column="is_adopted"/>
<!-- 审查依据现在直接存储为JSON字符串 -->
</resultMap>
<resultMap id="tenderResultVOMap" type="org.dromara.productManagement.domain.vo.TenderTaskResultVO">
<result property="name" column="category_name"/>
<collection property="results" javaType="java.util.ArrayList" ofType="org.dromara.productManagement.domain.vo.TenderTaskResultVO$ResultItem"
column="category_id" select="getTenderResultItemsByCategoryId"/>
</resultMap>
<select id="getResultsByTaskId" resultMap="tenderResultVOMap">
SELECT id as category_id, category_name
FROM tender_task_categories
WHERE tender_task_id = #{taskId}
</select>
<select id="getTenderResultItemsByCategoryId" resultMap="TenderTaskResult">
SELECT id, issue_name, original_text, compared_text, modified_content,
modification_display, existing_issues, review_basis, is_read, is_adopted,sort_order
FROM tender_task_result_details
WHERE category_id = #{category_id}
order by sort_order asc
</select>
</mapper>
Loading…
Cancel
Save