Browse Source

首件相关

huangjn 2 years ago
parent
commit
9d0573a525
14 changed files with 644 additions and 295 deletions
  1. 10 52
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/FirstInformation.java
  2. 6 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/InformationQuery.java
  3. 17 1
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/InformationQueryClient.java
  4. 0 23
      blade-service/blade-business/src/main/java/org/springblade/business/controller/FirstInformationController.java
  5. 12 2
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java
  6. 3 69
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/FirstInformationMapper.xml
  7. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml
  8. 0 26
      blade-service/blade-business/src/main/java/org/springblade/business/service/IFirstInformationService.java
  9. 2 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/IInformationQueryService.java
  10. 0 67
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/FirstInformationServiceImpl.java
  11. 158 14
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  12. 20 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/bean/TableInfo.java
  13. 288 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  14. 126 37
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

+ 10 - 52
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/FirstInformation.java

@@ -32,70 +32,28 @@ import java.util.Date;
  * @since 2022-06-20
  */
 @Data
-@TableName("u_first_information")
+@TableName("u_first_link_data")
 @EqualsAndHashCode(callSuper = true)
 public class FirstInformation extends BaseEntity {
 
     private static final long serialVersionUID = 1L;
 
     /**
-     * 节点ID
+     * 首件记录ID
      */
-    @ApiModelProperty("节点ID")
-    private Long wbsNodeId;
+    @ApiModelProperty("首件记录ID")
+    private Long firstId;
 
     /**
-     * 文件名称
+     * 关联的文件名称
      */
-    @ApiModelProperty("文件名称")
-    private String fileName;
+    @ApiModelProperty("关联的文件名称")
+    private String title;
 
     /**
-     * 填报时间
+     * 关联的文件ID,指向u_information_query的ID
      */
-    @ApiModelProperty("填报时间")
-    private String reportTime;
-
-    /**
-     * 数据ID,通过这个字段去寻找相关联的数据
-     */
-    private Long dataId;
-
-    /**
-     * 流程批次
-     */
-    @ApiModelProperty("流程批次")
-    private Integer reportNumber;
-
-    /**
-     * 创建人姓名
-     */
-    @ApiModelProperty("创建人姓名")
-    private String createUserName;
-
-    /**
-     * 流程ID
-     */
-    @ApiModelProperty("流程ID")
-    private String taskId;
-
-    /**
-     * 1施工2质检
-     */
-    @ApiModelProperty("1施工2质检")
-    private Integer classify;
-
-    public FirstInformation(String fileName, Long wbsNodeId, Integer reportNumber, Integer status, Long userId, String userName, Long deptId){
-        this.fileName = fileName;
-        this.wbsNodeId = wbsNodeId;
-        this.reportNumber = reportNumber;
-        this.setStatus(status);
-        this.setCreateUser(userId);
-        this.createUserName = userName;
-        this.setDataId(deptId);
-        this.setCreateTime(new Date());
-    }
-
-    public FirstInformation(){}
+    @ApiModelProperty("关联的文件ID,指向u_information_query的ID")
+    private Long linkId;
 
 }

+ 6 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/InformationQuery.java

@@ -107,4 +107,10 @@ public class InformationQuery extends BaseEntity {
     @ApiModelProperty("电签的PDF")
     private String eVisaPdfUrl;
 
+    @ApiModelProperty("表格ID,当是首件记录时(type = 3)有值")
+    private String tableId;
+
+    @ApiModelProperty("合并的pdfUrl,当是首件记录时(type = 3)有值")
+    private String linkMergePdfUrl;
+
 }

+ 17 - 1
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/InformationQueryClient.java

@@ -1,5 +1,6 @@
 package org.springblade.business.feign;
 
+import com.alibaba.fastjson.JSONObject;
 import org.springblade.common.constant.BusinessConstant;
 import org.springblade.core.secure.BladeUser;
 import org.springframework.cloud.openfeign.FeignClient;
@@ -7,6 +8,8 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import java.util.List;
+
 @FeignClient(value =
         BusinessConstant.APPLICATION_WEATHER_NAME
 )
@@ -17,6 +20,12 @@ public interface InformationQueryClient {
      */
     String API_PREFIX = "/api/business/informationQuery";
 
+    /**
+     * 获取记录
+     */
+    @PostMapping(API_PREFIX + "/queryFirstBusinessDataByFirstId")
+    JSONObject queryFirstBusinessDataByFirstId(@RequestParam String firstId);
+
     /**
      * 保存填报时新增或修改填报资料记录表数据
      * @param wbsId 当前填报节点
@@ -25,6 +34,13 @@ public interface InformationQueryClient {
      * @param sourceType 1原生2数据化
      */
     @PostMapping(API_PREFIX + "/saveOrUpdateInformationQueryData")
-    void saveOrUpdateInformationQueryData(@RequestParam String wbsId, @RequestParam String businessId, @RequestParam String fileName, @RequestParam Integer classify, @RequestParam Integer sourceType, @RequestParam String isFirst);
+    void saveOrUpdateInformationQueryData(@RequestParam String wbsId,
+                                          @RequestParam String tableId,
+                                          @RequestParam String businessId,
+                                          @RequestParam String fileName,
+                                          @RequestParam Integer classify,
+                                          @RequestParam Integer sourceType,
+                                          @RequestParam String isFirst,
+                                          @RequestBody List<JSONObject> linkDataList);
 
 }

+ 0 - 23
blade-service/blade-business/src/main/java/org/springblade/business/controller/FirstInformationController.java

@@ -1,16 +1,8 @@
 package org.springblade.business.controller;
 
 import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
-
-import org.springblade.core.mp.support.Condition;
-import org.springblade.core.mp.support.Query;
-import org.springblade.core.tool.api.R;
 import org.springframework.web.bind.annotation.*;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import org.springblade.business.vo.FirstInformationVO;
 import org.springblade.business.service.IFirstInformationService;
 import org.springblade.core.boot.ctrl.BladeController;
 
@@ -28,20 +20,5 @@ public class FirstInformationController extends BladeController {
 
 	private final IFirstInformationService firstInformationService;
 
-	/**
-	 * 自定义分页 首件信息记录表
-	 */
-	@GetMapping("/page")
-	@ApiOperationSupport(order = 1)
-	@ApiOperation(value = "分页")
-	public R<IPage<FirstInformationVO>> page(FirstInformationVO vo) {
-		//创建分页信息
-		Query query = new Query();
-		query.setCurrent(vo.getCurrent());
-		query.setSize(vo.getSize());
-
-		return R.data(firstInformationService.selectFirstInformationPage(Condition.getPage(query), vo));
-	}
-
 	
 }

+ 12 - 2
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java

@@ -1,10 +1,14 @@
 package org.springblade.business.feignClient;
 
+import com.alibaba.fastjson.JSONObject;
 import lombok.AllArgsConstructor;
+import org.springblade.business.entity.InformationQuery;
 import org.springblade.business.feign.InformationQueryClient;
 import org.springblade.business.service.IInformationQueryService;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 @RestController
 @AllArgsConstructor
 public class InformationQueryClientImpl implements InformationQueryClient {
@@ -12,7 +16,13 @@ public class InformationQueryClientImpl implements InformationQueryClient {
     private final IInformationQueryService iInformationQueryService;
 
     @Override
-    public void saveOrUpdateInformationQueryData(String wbsId, String businessId, String fileName, Integer classify, Integer sourceType, String isFirst) {
-        this.iInformationQueryService.saveOrUpdateInformationQueryData(wbsId, businessId, fileName, classify, sourceType, isFirst);
+    public JSONObject queryFirstBusinessDataByFirstId(String firstId) {
+        InformationQuery query = this.iInformationQueryService.getById(firstId);
+        return query != null ? JSONObject.parseObject(JSONObject.toJSONString(query), JSONObject.class) : null;
+    }
+
+    @Override
+    public void saveOrUpdateInformationQueryData(String wbsId, String tableId, String businessId, String fileName, Integer classify, Integer sourceType, String isFirst, List<JSONObject> linkDataList) {
+        this.iInformationQueryService.saveOrUpdateInformationQueryData(wbsId, tableId, businessId, fileName, classify, sourceType, isFirst, linkDataList);
     }
 }

+ 3 - 69
blade-service/blade-business/src/main/java/org/springblade/business/mapper/FirstInformationMapper.xml

@@ -6,81 +6,15 @@
     <resultMap id="firstInformationResultMap" type="org.springblade.business.entity.FirstInformation">
         <result column="id" property="id"/>
         <result column="create_user" property="createUser"/>
-        <result column="create_user_name" property="createUserName"/>
         <result column="create_dept" property="createDept"/>
         <result column="create_time" property="createTime"/>
         <result column="update_user" property="updateUser"/>
         <result column="update_time" property="updateTime"/>
         <result column="status" property="status"/>
         <result column="is_deleted" property="isDeleted"/>
-        <result column="wbs_node_id" property="wbsNodeId"/>
-        <result column="file_name" property="fileName"/>
-        <result column="data_id" property="dataId"/>
-        <result column="report_number" property="reportNumber"/>
-        <result column="report_time" property="reportTime"/>
-        <result column="task_id" property="taskId"/>
-        <result column="classify" property="classify"/>
+        <result column="first_id" property="firstId"/>
+        <result column="title" property="title"/>
+        <result column="link_id" property="linkId"/>
     </resultMap>
 
-    <select id="countFirstInformation" resultType="java.lang.Integer">
-        select count(id) from u_first_information
-        where
-          is_deleted = 0
-        <if test="vo.betweenTime != null and vo.betweenTime != ''">
-            and report_time between #{vo.startTime} and #{vo.endTime}
-        </if>
-        <if test="vo.status != null">
-            and status = #{vo.status}
-        </if>
-        <if test="vo.reportNumber != null">
-            and report_number = #{vo.reportNumber}
-        </if>
-        <if test="vo.queryValue != null and vo.queryValue != ''">
-            and file_name like concat('%',#{vo.queryValue},'%')
-        </if>
-        <if test="vo.wbsNodeArray != null and vo.wbsNodeArray.size > 0">
-            and wbs_node_id in
-            <foreach collection="vo.wbsNodeArray" item="wbsNodeIds" open="(" separator="," close=")">
-                #{wbsNodeIds}
-            </foreach>
-        </if>
-    </select>
-
-    <select id="selectFirstInformationPage" resultMap="firstInformationResultMap">
-        select
-          id,
-          file_name,
-          create_user_name,
-          report_number,
-          report_time,
-          wbs_node_id,
-          status,
-          data_id,
-          task_id,
-          classify
-        from u_first_information
-        where
-          is_deleted = 0
-        <if test="vo.betweenTime != null and vo.betweenTime != ''">
-            and report_time between #{vo.startTime} and #{vo.endTime}
-        </if>
-        <if test="vo.status != null">
-            and status = #{vo.status}
-        </if>
-        <if test="vo.reportNumber != null">
-            and report_number = #{vo.reportNumber}
-        </if>
-        <if test="vo.queryValue != null and vo.queryValue != ''">
-            and file_name like concat('%',#{vo.queryValue},'%')
-        </if>
-        <if test="vo.wbsNodeArray != null and vo.wbsNodeArray.size > 0">
-            and wbs_node_id in
-            <foreach collection="vo.wbsNodeArray" item="wbsNodeIds" open="(" separator="," close=")">
-                #{wbsNodeIds}
-            </foreach>
-        </if>
-        order by wbs_node_id, report_time DESC
-        limit ${current}, ${size}
-    </select>
-
 </mapper>

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml

@@ -30,6 +30,8 @@
         <result column="source_type" property="sourceType"/>
         <result column="pdf_url" property="pdfUrl"/>
         <result column="e_visa_pdf_url" property="eVisaPdfUrl"/>
+        <result column="table_id" property="tableId"/>
+        <result column="link_merge_pdf_url" property="linkMergePdfUrl"/>
     </resultMap>
 
     <resultMap id="queryProcessDataMap" type="org.springblade.business.vo.QueryProcessDataVO">

+ 0 - 26
blade-service/blade-business/src/main/java/org/springblade/business/service/IFirstInformationService.java

@@ -17,9 +17,7 @@
 package org.springblade.business.service;
 
 import org.springblade.business.entity.FirstInformation;
-import org.springblade.business.vo.FirstInformationVO;
 import org.springblade.core.mp.base.BaseService;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 
 /**
  * 首件信息记录表 服务类
@@ -29,28 +27,4 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
  */
 public interface IFirstInformationService extends BaseService<FirstInformation> {
 
-	/**
-	 * 修改首件记录表信息
-	 * @param id 主键
-	 * @param fileName 文件名称
-	 * @param reportNumber 上报批次
-	 * @param status 流程状态
-	 * @return 修改结果
-	 */
-	Boolean updateFirstInformation(Long id, String fileName, Integer reportNumber, Integer status);
-
-	/**
-	 * 保存首件记录表信息
-	 * @param wbsNodeId 当前资料所在节点ID
-	 * @param fileName 文件名称
-	 * @param dataId 数据ID
-	 * @return 保存后数据的ID
-	 */
-	Long saveFirstInformation(Long wbsNodeId, String fileName, Long dataId);
-
-	/**
-	 * 自定义分页
-	 */
-	IPage<FirstInformationVO> selectFirstInformationPage(IPage<FirstInformationVO> page, FirstInformationVO vo);
-
 }

+ 2 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/IInformationQueryService.java

@@ -16,6 +16,7 @@
  */
 package org.springblade.business.service;
 
+import com.alibaba.fastjson.JSONObject;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.business.vo.FileUserVO;
 import org.springblade.business.vo.InformationQueryVO;
@@ -68,7 +69,7 @@ public interface IInformationQueryService extends BaseService<InformationQuery>
 	 * @param classify 1施工2质检
 	 * @param sourceType 1原生2数据化
 	 */
-	void saveOrUpdateInformationQueryData(String wbsId, String businessId, String fileName, Integer classify, Integer sourceType, String isFirst);
+	void saveOrUpdateInformationQueryData(String wbsId, String tableId, String businessId, String fileName, Integer classify, Integer sourceType, String isFirst, List<JSONObject> linkDataList);
 
 	/**
 	 * 获取当前合同段下所有的上报批次

+ 0 - 67
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/FirstInformationServiceImpl.java

@@ -16,23 +16,11 @@
  */
 package org.springblade.business.service.impl;
 
-import cn.hutool.core.date.DateUtil;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import org.apache.commons.lang.StringUtils;
 import org.springblade.business.entity.FirstInformation;
-import org.springblade.business.vo.FirstInformationVO;
 import org.springblade.business.mapper.FirstInformationMapper;
 import org.springblade.business.service.IFirstInformationService;
-import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springblade.core.secure.BladeUser;
-import org.springblade.core.secure.utils.AuthUtil;
 import org.springframework.stereotype.Service;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-
-import java.util.Date;
-import java.util.List;
 
 /**
  * 首件信息记录表 服务实现类
@@ -43,59 +31,4 @@ import java.util.List;
 @Service
 public class FirstInformationServiceImpl extends BaseServiceImpl<FirstInformationMapper, FirstInformation> implements IFirstInformationService {
 
-	@Override
-	public Boolean updateFirstInformation(Long id, String fileName, Integer reportNumber, Integer status) {
-		if(StringUtils.isEmpty(fileName) && reportNumber == null && status == null){
-			return null;
-		} else {
-			FirstInformation update = new FirstInformation();
-			update.setId(id);
-			if(StringUtils.isNotEmpty(fileName)){
-				update.setFileName(fileName);
-			}
-			if(reportNumber != null){
-				update.setReportNumber(reportNumber);
-			}
-			if(status != null){
-				update.setStatus(status);
-			}
-			return this.updateById(update);
-		}
-	}
-
-	@Override
-	public Long saveFirstInformation(Long wbsNodeId, String fileName, Long dataId) {
-		BladeUser bladeUser = AuthUtil.getUser();
-		FirstInformation newData = new FirstInformation(fileName, wbsNodeId, null, 0, bladeUser.getUserId(), bladeUser.getUserName(), bladeUser.getDeptId().contains(",") ? Long.parseLong(bladeUser.getDeptId().split(",")[0]) : Long.parseLong(bladeUser.getDeptId()));
-		newData.setId(SnowFlakeUtil.getId());
-		//将主键返回,保存失败返回null
-		return this.save(newData) ? newData.getId() : null;
-	}
-
-	@Override
-	public IPage<FirstInformationVO> selectFirstInformationPage(IPage<FirstInformationVO> page, FirstInformationVO vo) {
-		//处理分页相关
-		Long current = (page.getCurrent() - 1L) * page.getSize();
-		if(StringUtils.isNotEmpty(vo.getWbsId()) && !",".equals(vo.getWbsId())){
-			List<String> wbsNodeArray = JSONArray.parseArray(JSONObject.toJSONString(vo.getWbsId().split(",")), String.class);
-			wbsNodeArray.removeIf(StringUtils::isEmpty);
-			vo.setWbsNodeArray(wbsNodeArray);
-		}
-		if(StringUtils.isNotEmpty(vo.getBetweenTime())){
-			if(vo.getBetweenTime().contains("~")){
-				String[] between = vo.getBetweenTime().split("~");
-				vo.setStartTime(between[0].trim());
-				vo.setEndTime(between[1].trim());
-			} else {
-				vo.setStartTime(vo.getBetweenTime().trim());
-				vo.setEndTime(DateUtil.format(new Date(), "yyyy-MM-dd"));
-			}
-		}
-		//获取列表总数
-		int countValue = this.baseMapper.countFirstInformation(vo);
-		//设置总数
-		page.setTotal(countValue);
-		return page.setRecords(this.baseMapper.selectFirstInformationPage(current, page.getSize(), vo));
-	}
-
 }

+ 158 - 14
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java

@@ -2,26 +2,35 @@ package org.springblade.business.service.impl;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.client.utils.DateUtils;
+import org.springblade.business.entity.FirstInformation;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.business.entity.Task;
 import org.springblade.business.entity.TaskParallel;
 import org.springblade.business.feign.TaskClient;
+import org.springblade.business.service.IFirstInformationService;
 import org.springblade.business.service.ITaskParallelService;
+import org.springblade.business.utils.FileUtils;
 import org.springblade.business.vo.FileUserVO;
 import org.springblade.business.vo.InformationQueryVO;
 import org.springblade.business.mapper.InformationQueryMapper;
 import org.springblade.business.service.IInformationQueryService;
 import org.springblade.business.vo.QueryProcessDataVO;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.feign.WbsTreeContractClient;
 import org.springblade.manager.vo.WbsTreeContractTreeVOS;
+import org.springblade.resource.feign.NewIOSSClient;
+import org.springblade.system.cache.ParamCache;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
 import org.springframework.stereotype.Service;
@@ -48,6 +57,10 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
 
 	private final ITaskParallelService taskParallelService;
 
+	private final IFirstInformationService firstInformationService;
+
+	private final NewIOSSClient newIOSSClient;
+
 	@Override
 	public List<String> queryBusinessTableData(String formDataId) {
 		//获取具体业务数据
@@ -92,22 +105,75 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
 		return result;
 	}
 
-	@Override
-	public void saveOrUpdateInformationQueryData(String primaryKeyId, String businessId, String fileName, Integer classify, Integer sourceType, String isFirst) {
-		BladeUser user = AuthUtil.getUser();
+	private List<FirstInformation> setFirstLinkData(List<JSONObject> linkDataList, String businessId){
+		List<FirstInformation> linkList = new ArrayList<>();
 
-		//首先根据wbsId获取合同段ID和项目ID
-		WbsTreeContract contractTree = this.wbsTreeContractClient.getContractWbsTreeByPrimaryKeyId(Long.parseLong(primaryKeyId));
+		Date nowDate = new Date();
+		linkDataList.forEach(json -> {
+			FirstInformation linkData = new FirstInformation();
+			linkData.setFirstId(Long.parseLong(businessId));
+			linkData.setTitle(json.getString("title"));
+			linkData.setLinkId(json.getLong("id"));
+
+			linkData.setCreateUser(AuthUtil.getUserId());
+			linkData.setCreateTime(nowDate);
+
+			linkList.add(linkData);
+		});
+
+		return linkList;
+	}
+
+	private void updateLinkMergePdfUrl(List<JSONObject> linkDataList, InformationQuery data, String businessId){
+		//保存关联数据
+		if(linkDataList != null && linkDataList.size() > 0){
+			try{
+				//获取配置的路径
+				String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+
+				//获取关联的数据
+				List<String> linkIds = linkDataList.stream().map(json -> json.getString("id")).distinct().collect(Collectors.toList());
+				//查询数据
+				List<InformationQuery> linkList = this.listByIds(linkIds);
+				//获取pdfUrl
+				List<String> pdfUrls = linkList.stream().map(query -> StringUtils.isNotEmpty(query.getEVisaPdfUrl()) ? query.getEVisaPdfUrl() : query.getPdfUrl()).distinct().collect(Collectors.toList());
+
+
+				String mergeFileName = SnowFlakeUtil.getId() + ".pdf", margePdfPath = file_path + "/pdf//" + mergeFileName;
+				//合并
+				FileUtils.mergePdfPublicMethods(pdfUrls, margePdfPath);
+				//上传
+				BladeFile file = this.newIOSSClient.uploadFile(mergeFileName, margePdfPath);
+				if(file != null){
+					data.setLinkMergePdfUrl(file.getLink());
+				}
+
+				//保存关联
+				this.firstInformationService.saveBatch(this.setFirstLinkData(linkDataList, businessId));
+			}catch (Exception e){
+				e.printStackTrace();
+			}
+		}
+
+
+	}
 
-		//判断当前填报节点下是否已经存在相应数据
-		InformationQuery oldData = this.baseMapper.getInformationQueryByWbsId(contractTree.getPKeyId(), classify);
+	private void saveOrUpdateFirstInformationQueryData(String primaryKeyId, String tableId, String businessId, String fileName, Integer classify, Integer sourceType, List<JSONObject> linkDataList){
+
+		BladeUser user = AuthUtil.getUser();
+		//获取绑定的节点信息
+		WbsTreeContract contractTree = this.wbsTreeContractClient.getContractWbsTreeByPrimaryKeyId(Long.parseLong(primaryKeyId));
 
+		InformationQuery oldData = this.getById(businessId);
 		if(oldData != null){
 			//存在记录,修改
 			if(StringUtils.isNotEmpty(fileName)){
 				oldData.setName(fileName);
 			}
 
+			oldData.setUpdateTime(new Date());
+			oldData.setUpdateUser(user.getUserId());
+
 			//拼接填报人信息
 			String fileUser = user.getUserId() + "-" + user.getNickName();
 			if(StringUtils.isNotEmpty(oldData.getFileUserIdAndName())){
@@ -119,13 +185,22 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
 				oldData.setFileUserIdAndName(fileUser);
 			}
 
-			oldData.setUpdateTime(new Date());
-			oldData.setUpdateUser(user.getUserId());
+			//删除关联关系
+			this.firstInformationService.update(Wrappers.<FirstInformation>lambdaUpdate().set(FirstInformation::getIsDeleted, 1).eq(FirstInformation::getFirstId, businessId));
+			//重新添加并处理合并的pdf
+			this.updateLinkMergePdfUrl(linkDataList, oldData, businessId);
+
 			//修改数据
 			this.baseMapper.updateById(oldData);
+
 		} else {
-			//新增基础数据
+			//新增
 			InformationQuery newData = new InformationQuery();
+			//处理关联数据及合并pdf
+			this.updateLinkMergePdfUrl(linkDataList, newData, businessId);
+
+			//数据ID
+			newData.setId(Long.parseLong(businessId));
 			//设置文件题名
 			newData.setName(fileName);
 			//设置文件类型
@@ -140,10 +215,7 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
 			newData.setWbsId(contractTree.getPKeyId());
 
 			//1资料填报,2试验,3首件
-			newData.setType(StringUtils.isNotEmpty(isFirst) ? 3 : (contractTree.getIsExpernode() == null || contractTree.getIsExpernode() <= 0) ? 1 : 2);
-
-			//数据ID
-//			newData.setDataId(dataId);
+			newData.setType(3);
 
 			//流程状态,默认未上报
 			newData.setStatus(0);
@@ -153,8 +225,80 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
 			newData.setSourceType(sourceType);
 			newData.setCreateUser(user.getUserId());
 			newData.setCreateTime(new Date());
+
+			newData.setTableId(tableId);
+
 			//保存数据
 			this.baseMapper.insert(newData);
+
+		}
+
+	}
+
+	@Override
+	public void saveOrUpdateInformationQueryData(String primaryKeyId, String tableId, String businessId, String fileName, Integer classify, Integer sourceType, String isFirst, List<JSONObject> linkDataList) {
+		BladeUser user = AuthUtil.getUser();
+
+		if(StringUtils.isNotEmpty(isFirst) && "true".equals(isFirst)){
+			this.saveOrUpdateFirstInformationQueryData(primaryKeyId, tableId, businessId, fileName, classify, sourceType, linkDataList);
+		} else {
+			//首先根据wbsId获取合同段ID和项目ID
+			WbsTreeContract contractTree = this.wbsTreeContractClient.getContractWbsTreeByPrimaryKeyId(Long.parseLong(primaryKeyId));
+
+			//判断当前填报节点下是否已经存在相应数据
+			InformationQuery oldData = this.baseMapper.getInformationQueryByWbsId(contractTree.getPKeyId(), classify);
+
+			if(oldData != null){
+				//存在记录,修改
+				if(StringUtils.isNotEmpty(fileName)){
+					oldData.setName(fileName);
+				}
+
+				//拼接填报人信息
+				String fileUser = user.getUserId() + "-" + user.getNickName();
+				if(StringUtils.isNotEmpty(oldData.getFileUserIdAndName())){
+					if(!oldData.getFileUserIdAndName().contains(user.getUserId().toString())){
+						//不包含,拼接
+						oldData.setFileUserIdAndName(oldData.getFileUserIdAndName() + "," + fileUser);
+					}
+				} else {
+					oldData.setFileUserIdAndName(fileUser);
+				}
+
+				oldData.setUpdateTime(new Date());
+				oldData.setUpdateUser(user.getUserId());
+				//修改数据
+				this.baseMapper.updateById(oldData);
+			} else {
+				//新增基础数据
+				InformationQuery newData = new InformationQuery();
+				//设置文件题名
+				newData.setName(fileName);
+				//设置文件类型
+				newData.setCategory(contractTree.getNodeType());
+				//项目ID
+				newData.setProjectId(Long.parseLong(contractTree.getProjectId()));
+				//合同段ID
+				newData.setContractId(Long.parseLong(contractTree.getContractId()));
+				//施工资料还是质检资料
+				newData.setClassify(classify);
+				//节点ID
+				newData.setWbsId(contractTree.getPKeyId());
+
+				//1资料填报,2试验,3首件
+				newData.setType((contractTree.getIsExpernode() == null || contractTree.getIsExpernode() <= 0) ? 1 : 2);
+
+				//流程状态,默认未上报
+				newData.setStatus(0);
+				//填报人ID及姓名
+				newData.setFileUserIdAndName(user.getUserId() + "-" + user.getNickName());
+				//数据源类型
+				newData.setSourceType(sourceType);
+				newData.setCreateUser(user.getUserId());
+				newData.setCreateTime(new Date());
+				//保存数据
+				this.baseMapper.insert(newData);
+			}
 		}
 
 	}

+ 20 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/bean/TableInfo.java

@@ -19,11 +19,30 @@ public class TableInfo {
     private String projectId;
     private String groupId;
 
+    // =============================== 首件相关 start ===============================
     /**
      * huangjn 2022-09-08 11:18 是否是首件填报
      */
     private String isFirst;
 
+    /**
+     * 首件绑定的节点
+     */
+    private String firstNodeId;
+
+    /**
+     * 首件记录ID(修改时有值,新增时为空)
+     */
+    private String firstId;
+
+    /**
+     * 首件关联的资料信息
+     */
+    private List<Object> linkProcessList;
+
+    // =============================== 首件相关 end ===============================
+
+    // =============================== 日志相关 start ===============================
     /**
      * huangjn 2022-09-14 15:27 是否是日志填报
      */
@@ -48,5 +67,6 @@ public class TableInfo {
      * id,用于给日志关联的工序信息做特殊化处理
      */
     private String businessId;
+    // =============================== 日志相关 end ===============================
 
 }

+ 288 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -25,6 +25,7 @@ import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
 import org.springblade.business.feign.ContractLogClient;
+import org.springblade.business.feign.InformationQueryClient;
 import org.springblade.business.vo.SaveContractLogVO;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
@@ -124,6 +125,8 @@ public class ExcelTabController extends BladeController {
 
     private final ContractLogClient contractLogClient;
 
+    private final InformationQueryClient informationQueryClient;
+
     /**
      * 详情
      */
@@ -1934,7 +1937,7 @@ public class ExcelTabController extends BladeController {
                         queryWrapper.eq("type", 2);
                         queryWrapper.eq("tab_id", tableNode.getPKeyId());
 
-                        final List<TextdictInfo> textdictInfos = textdictInfoService.getBaseMapper().selectList(queryWrapper);
+                        final List<TextdictInfo> textdictInfos = this.textdictInfoService.getBaseMapper().selectList(queryWrapper);
                         if (textdictInfos != null && !textdictInfos.isEmpty()) {
                             textdictInfos.forEach(e -> {
                                 String key = e.getColKey();
@@ -1962,7 +1965,7 @@ public class ExcelTabController extends BladeController {
 
                 sheet.saveToPdf(onePdfPath);
 
-                BladeFile bladeFile = newIOSSClient.uploadFile( fileName + ".pdf", onePdfPath);
+                BladeFile bladeFile = this.newIOSSClient.uploadFile( fileName + ".pdf", onePdfPath);
 
                 pdfUrls.add(bladeFile.getLink());
 
@@ -1979,7 +1982,7 @@ public class ExcelTabController extends BladeController {
 
                     FileUtils.mergePdfPublicMethods(pdfUrls, mergePdfPath);
 
-                    BladeFile mergeFile = newIOSSClient.uploadFile(theLogId + new Date().getTime() + ".pdf", mergePdfPath);
+                    BladeFile mergeFile = this.newIOSSClient.uploadFile(theLogId + new Date().getTime() + ".pdf", mergePdfPath);
 
                     //修改记录
                     this.contractLogClient.updateTheLogPdfUrl(theLogJson.getString("id"), mergeFile.getLink());
@@ -2194,4 +2197,286 @@ public class ExcelTabController extends BladeController {
         return null;
     }
 
+    /**
+     * 获取首件填报记录
+     */
+    @GetMapping("/get-first-business-data")
+    @ApiOperationSupport(order = 28)
+    @ApiOperation(value = "获取首件填报记录")
+    @ApiImplicitParam(name = "firstId", value = "首件列表ID")
+    public R<List<Map<String, Object>>> getFirstBusinessData(String firstId){
+        if(StringUtils.isNotEmpty(firstId)){
+            List<Map<String, Object>> result = new ArrayList<>();
+
+            JSONObject json = this.informationQueryClient.queryFirstBusinessDataByFirstId(firstId);
+            if(json != null){
+                //获取数据所在表格
+                WbsTreeContract tableNode = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, json.getString("tableId")));
+                if(tableNode != null && StringUtils.isNotEmpty(tableNode.getInitTableName())){
+                    //获取填报数据
+                    List<Map<String, Object>> businessDataMapList = this.jdbcTemplate.queryForList("SELECT * FROM " + tableNode.getInitTableName() + " WHERE group_id = " + json.getString("id"));
+                    if(businessDataMapList.size() > 0){
+                        for(Map<String, Object> mysqlData : businessDataMapList){
+                            //数据结果
+                            Map<String, Object> reData = new HashMap<>();
+
+                            for (String key : mysqlData.keySet()) {
+                                String tabVal = mysqlData.get(key) + "";
+                                // 时间段处理
+                                if (StringUtils.isNotEmpty(tabVal) && !tabVal.equals("null")) {
+                                    if (tabVal.indexOf("T") >= 0 && tabVal.indexOf(".000Z]") >= 0) {
+                                        String tabData[] = tabVal.split("_\\^_");
+
+                                        if (reData.containsKey("pickerKey")) {
+                                            String pickerKey = reData.get("pickerKey") + "," + key + "__" + tabData[1];
+                                            reData.put("pickerKey", pickerKey);
+                                        } else {
+                                            reData.put("pickerKey", key + "__" + tabData[1]);
+                                        }
+
+                                        String sql = tabData[0];
+                                        sql = sql.replaceAll("\\[", "['");
+                                        sql = sql.replaceAll("]", "\']");
+                                        sql = sql.replaceAll("000Z,", "000Z\',");
+                                        sql = sql.replaceAll(", 20", ", \'20");
+                                        sql = sql.replaceAll("'", "");
+                                        reData.put(key + "__" + tabData[1], sql);
+                                    } else if (tabVal.indexOf("T") >= 0 && tabVal.indexOf(".000Z") >= 0) { //时间
+
+                                        String tabData[] = tabVal.split("_\\^_");
+                                        reData.put(key + "__" + tabData[1], tabData[0]);
+
+                                    } else if (tabVal.indexOf("☆") >= 0) {
+                                        String mysql[] = tabVal.split("☆");
+                                        for (String data : mysql) {
+                                            String tabData[] = data.split("_\\^_");
+                                            reData.put(key + "__" + tabData[1], tabData[0]);
+                                        }
+                                    } else if (tabVal.indexOf("_^_") >= 0) {
+                                        String tabData[] = tabVal.split("_\\^_");
+                                        reData.put(key + "__" + tabData[1], tabData[0]);
+                                    } else {
+                                        reData.put(key, tabVal);
+                                    }
+                                }
+                            }
+
+                            reData.remove("p_key_id");
+                            reData.remove("classify");
+                            reData.remove("contractId");
+                            reData.remove("pkeyId");
+                            reData.remove("projectId");
+
+                            result.add(reData);
+                        }
+
+                        return R.data(result);
+                    }
+                }
+            }
+        }
+
+        return R.data(300, null, "未找到对应的业务数据");
+    }
+
+    /**
+     * 预览首件PDF
+     */
+    @GetMapping("/get-first-pdf-info")
+    @ApiOperationSupport(order = 28)
+    @ApiOperation(value = "获取首件填报记录")
+    @ApiImplicitParam(name = "firstId", value = "首件列表ID")
+    public R<String> getFirstPdfInfo(String firstId){
+        if(StringUtils.isNotEmpty(firstId)){
+            //PDF路径集合
+            List<String> pdfUrls = new ArrayList<>();
+
+            //获取配置的路径
+            String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+            //获取数据
+            JSONObject firstJson = this.informationQueryClient.queryFirstBusinessDataByFirstId(firstId);
+            if(firstJson != null){
+                if(StringUtils.isNotEmpty(firstJson.getString("eVisaPdfUrl")) || StringUtils.isNotEmpty(firstJson.getString("pdfUrl"))){
+                    pdfUrls.add(StringUtils.isNotEmpty(firstJson.getString("eVisaPdfUrl")) ? firstJson.getString("eVisaPdfUrl") : firstJson.getString("pdfUrl"));
+                } else {
+                    //没有生成拼接的记录,生成
+                    //获取html
+                    WbsTreeContract tableNode = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, firstJson.getString("tableId")));
+
+                    if(tableNode == null){
+                        return R.fail("该数据下无此节点!");
+                    }
+
+                    if(StringUtils.isEmpty(tableNode.getHtmlUrl())){
+                        return R.fail("请关联清表!");
+                    }
+
+                    // 获取清表信息
+                    ExcelTab excelTab = excelTabService.getById(tableNode.getExcelId());
+                    if (excelTab == null) {
+                        return R.fail("失败");
+                    }
+
+                    List<Map<String, Object>> businessDataMapList = this.getFirstBusinessData(firstId).getData();
+
+                    try{
+                        //处理数据
+                        for(Map<String, Object> dataMap : businessDataMapList){
+                            // 获取excel流 和 html流
+                            Workbook wb = new Workbook();
+                            wb.loadFromMHtml(CommonUtil.getOSSInputStream(excelTab.getFileUrl()));
+                            //获取工作表
+                            Worksheet sheet = wb.getWorksheets().get(0);
+
+                            // 数据不为空 &&
+                            if (StringUtils.isNotEmpty(tableNode.getHtmlUrl())) {
+                                File htmlFile = ResourceUtil.getFile(tableNode.getHtmlUrl());
+                                if (htmlFile.exists()) {
+                                    String htmlString = IoUtil.readToString(new FileInputStream(htmlFile));
+                                    Document doc = Jsoup.parse(htmlString);
+                                    Element table = doc.select("table").first();
+                                    Elements trs = table.select("tr");
+
+                                    if (ObjectUtil.isNotEmpty(dataMap)) {
+                                        for (String val : dataMap.keySet()) {
+                                            if (val.indexOf("__") >= 0) {
+                                                String DataVal[] = val.split("__");
+                                                String[] xy = DataVal[1].split("_");
+                                                Element data = trs.get(Integer.parseInt(xy[0])).select("td").get(Integer.parseInt(xy[1]));
+
+                                                if (data.html().indexOf("x1") >= 0 && data.html().indexOf("y1") >= 0) {
+                                                    int x1, y1;
+
+                                                    if (data.html().indexOf("el-tooltip") >= 0) {
+                                                        x1 = Integer.parseInt(data.children().get(0).children().get(0).attr("x1"));
+                                                        y1 = Integer.parseInt(data.children().get(0).children().get(0).attr("y1"));
+                                                    } else {
+                                                        x1 = Integer.parseInt(data.children().get(0).attr("x1"));
+                                                        y1 = Integer.parseInt(data.children().get(0).attr("y1"));
+                                                    }
+                                                    if (x1 == 0) {
+                                                        x1 = 1;
+                                                    }
+                                                    String myData = dataMap.get(val) + "";
+                                                    if (myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0) {
+                                                        if (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0) {
+                                                            myData = myData.replace("[", "").replace("]", "");
+                                                            String[] dataVal = myData.split(",");
+                                                            String Start_dataStr[] = dataVal[0].split("T")[0].split("-");
+                                                            String StartDate = StringUtil.format("{}年{}月{}日", new Object[]{Start_dataStr[0], Start_dataStr[1], Integer.parseInt(Start_dataStr[2]) + 1});
+
+                                                            String end_dataStr[] = dataVal[1].split("T")[0].split("-");
+                                                            String endDate = StringUtil.format("{}年{}月{}日", new Object[]{end_dataStr[0], end_dataStr[1], Integer.parseInt(end_dataStr[2]) + 1});
+
+                                                            if (StartDate.equals(endDate)) {
+                                                                myData = StartDate;
+                                                            } else {
+                                                                myData = StartDate + "-" + endDate;
+                                                            }
+                                                        } else {
+                                                            String dataStr[] = myData.split("T")[0].split("-");
+                                                            myData = StringUtil.format("{}年{}月{}日", new Object[]{dataStr[0], dataStr[1], Integer.parseInt(dataStr[2]) + 1});
+                                                        }
+                                                    }
+
+                                                    if (myData.indexOf("https") >= 0 && myData.indexOf("aliyuncs") >= 0) {
+                                                        Element element = trs.get(y1).select("td").get(x1);
+                                                        String styles[] = element.attr("style").split(";");
+                                                        int Height = 0;
+                                                        for (String sty : styles) {
+                                                            if (sty.indexOf("height:") >= 0) {
+                                                                Height = Integer.parseInt(sty.replace("height:", "").replace("px", ""));
+                                                            }
+                                                        }
+
+                                                        BufferedImage image = ImageIO.read(CommonUtil.getOSSInputStream(myData));
+                                                        ExcelPicture pic = sheet.getPictures().add(y1, x1, image);
+                                                        pic.setHeight(Height);
+                                                        sheet.getCellRange(y1, x1).getStyle().setShrinkToFit(true);
+
+                                                    } else {
+                                                        final CellRange cellRange = sheet.getCellRange(y1, x1);
+                                                        cellRange.setText(myData);
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+
+                                    // 组装电签设置
+                                    QueryWrapper<TextdictInfo> queryWrapper = new QueryWrapper<>();
+                                    queryWrapper.eq("type", 2);
+                                    queryWrapper.eq("tab_id", tableNode.getPKeyId());
+
+                                    final List<TextdictInfo> textdictInfos = textdictInfoService.getBaseMapper().selectList(queryWrapper);
+                                    if (textdictInfos != null && !textdictInfos.isEmpty()) {
+                                        textdictInfos.forEach(e -> {
+                                            String key = e.getColKey();
+                                            String keys[] = key.split("__");
+                                            String[] trtd = keys[1].split("_");
+                                            Element data = trs.get(Integer.parseInt(trtd[0])).select("td").get(Integer.parseInt(trtd[1]));
+                                            int x1 = Integer.parseInt(data.children().get(0).attr("x1"));
+                                            if (x1 == 0) {
+                                                x1 = 1;
+                                            }
+                                            int y1 = Integer.parseInt(data.children().get(0).attr("y1"));
+
+                                            final CellRange cellRange = sheet.getCellRange(y1, x1);
+
+                                            cellRange.setText(e.getId() + "");
+                                            cellRange.getCellStyle().getFont().setColor(Color.white);
+
+                                        });
+                                    }
+                                }
+                            }
+
+                            Long fileName = SnowFlakeUtil.getId();
+                            String onePdfPath = file_path + "/pdf//" + fileName + ".pdf";
+
+                            sheet.saveToPdf(onePdfPath);
+
+                            BladeFile bladeFile = this.newIOSSClient.uploadFile( fileName + ".pdf", onePdfPath);
+
+                            pdfUrls.add(bladeFile.getLink());
+
+                            wb.dispose();
+                        }
+                    }catch (Exception e){
+                        e.printStackTrace();
+                    }
+                }
+
+                if(pdfUrls.size() > 0){
+                    try{
+                        //关联的数据
+                        if(StringUtils.isNotEmpty(firstJson.getString("linkMergePdfUrl"))){
+                            pdfUrls.add(firstJson.getString("linkMergePdfUrl"));
+                        }
+                        //总结报告,暂时无
+
+                        //上传
+                        String mergePdfPath = file_path + "/pdf//" + firstId + ".pdf";
+                        File oldMergePdf = ResourceUtil.getFile(mergePdfPath);
+                        if (oldMergePdf.exists()) {
+                            oldMergePdf.delete();
+                        }
+                        //合并
+                        FileUtils.mergePdfPublicMethods(pdfUrls, mergePdfPath);
+                        //上传
+                        BladeFile mergeFile = this.newIOSSClient.uploadFile(firstId + '-' + new Date().getTime() + ".pdf", mergePdfPath);
+
+                        //返回
+                        return R.data(mergeFile.getLink());
+
+                    }catch (Exception e){
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+
+        return R.data(300, null, "未找到数据");
+    }
+
 }

+ 126 - 37
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -145,6 +145,58 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 		return null;
 	}
 
+	private void setFirstData(JSONObject dataInfo2, TableInfo tableInfo){
+		//huangjn 判断是否是首件
+		if(dataInfo2.containsKey("isFirst")){
+			tableInfo.setIsFirst(dataInfo2.getString("isFirst"));
+		}
+		//huangjn 判断是否是首件
+
+		//首件资料绑定的节点
+		if(dataInfo2.containsKey("firstNodeId")){
+			tableInfo.setFirstNodeId(dataInfo2.getString("firstNodeId"));
+		}
+		//首件ID(编辑时有值,新增时为空)
+		if(dataInfo2.containsKey("firstId")){
+			tableInfo.setFirstId(dataInfo2.getString("firstId"));
+		}
+
+	}
+
+	/**
+	 * 设置日志信息
+	 */
+	private void setTheLogData(JSONObject dataInfo2, TableInfo tableInfo){
+		//huangjn 判断是否是日志
+		if(dataInfo2.containsKey("isTheLog")){
+			tableInfo.setIsTheLog(dataInfo2.getString("isTheLog"));
+		}
+		//huangjn 判断是否是日志
+
+		//huangjn 日志ID
+		if(dataInfo2.containsKey("theLogId")){
+			tableInfo.setTheLogId(dataInfo2.getString("theLogId"));
+		}
+		//huangjn 日志ID
+
+		//huangjn 日志勾选的工序
+		if(dataInfo2.containsKey("linkTabIds")){
+			tableInfo.setLinkTabIds(dataInfo2.getJSONArray("linkTabIds"));
+		}
+		//huangjn 日志勾选的工序
+
+		//huangjn 日志所选时间
+		if(dataInfo2.containsKey("recordTime")){
+			tableInfo.setRecordTime(dataInfo2.getString("recordTime"));
+		}
+		//huangjn 日志所选时间
+		//huangjn 每份填报数据的id,目前日志专用
+		if(dataInfo2.containsKey("id")){
+			tableInfo.setBusinessId(dataInfo2.getString("id"));
+		}
+		//huangjn 每份填报数据的id,目前日志专用
+	}
+
 	@Override
 	public List<TableInfo> getTableInfoList(JSONArray dataArray) {
 		if(dataArray!=null&&!dataArray.isEmpty()){
@@ -160,40 +212,10 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 				tableInfo.setClassify(dataInfo2.getString("classify"));
 				//huangjn 填报的类型,施工或监理
 
-				//huangjn 判断是否是首件
-				if(dataInfo2.containsKey("isFirst")){
-					tableInfo.setIsFirst(dataInfo2.getString("isFirst"));
-				}
-				//huangjn 判断是否是首件
-
-				//huangjn 判断是否是日志
-				if(dataInfo2.containsKey("isTheLog")){
-					tableInfo.setIsTheLog(dataInfo2.getString("isTheLog"));
-				}
-				//huangjn 判断是否是日志
-
-				//huangjn 日志ID
-				if(dataInfo2.containsKey("theLogId")){
-					tableInfo.setTheLogId(dataInfo2.getString("theLogId"));
-				}
-				//huangjn 日志ID
-
-				//huangjn 日志勾选的工序
-				if(dataInfo2.containsKey("linkTabIds")){
-					tableInfo.setLinkTabIds(dataInfo2.getJSONArray("linkTabIds"));
-				}
-				//huangjn 日志勾选的工序
-
-				//huangjn 日志所选时间
-				if(dataInfo2.containsKey("recordTime")){
-					tableInfo.setRecordTime(dataInfo2.getString("recordTime"));
-				}
-				//huangjn 日志所选时间
-				//huangjn 每份填报数据的id,目前日志专用
-				if(dataInfo2.containsKey("id")){
-					tableInfo.setBusinessId(dataInfo2.getString("id"));
-				}
-				//huangjn 每份填报数据的id,目前日志专用
+				//设置首件信息
+				this.setFirstData(dataInfo2, tableInfo);
+				//设置日志信息
+				this.setTheLogData(dataInfo2, tableInfo);
 
 				dataInfo2.fluentRemove("contractId")
 						 .fluentRemove("pkeyId")
@@ -203,10 +225,12 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 				         .fluentRemove("pickerKey")
 				         .fluentRemove("id")
 						 .fluentRemove("isFirst")
+						 .fluentRemove("firstNodeId")
 						 .fluentRemove("isTheLog")
 						 .fluentRemove("theLogId")
 						 .fluentRemove("linkTabIds")
 						 .fluentRemove("recordTime")
+						 .fluentRemove("businessId")
 				         .fluentRemove("");
 				// 计算数据
 				LinkedHashMap<String,List<String>> dataMap =dataInfo2.keySet().stream().filter(e->e.contains("__")).collect(Collectors.groupingBy(e->e.split("__")[0], LinkedHashMap<String,List<String>>::new,Collectors.toList()));
@@ -379,10 +403,75 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
 	}
 
+	private void saveOrUpdateFirst(List<TableInfo> tableInfoList){
+		//获取首件绑定的节点
+		String firstNodeId = tableInfoList.get(0).getFirstNodeId();
+		//获取首件关联的施工记录
+		List<JSONObject> linkProcessList = JSONArray.parseArray(JSONObject.toJSONString(tableInfoList.get(0).getLinkProcessList()), JSONObject.class);
+		if(linkProcessList == null){
+			linkProcessList = new ArrayList<>();
+		}
+
+		//获取数据所在数据表名
+		WbsTreeContract table = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, tableInfoList.get(0).getPkeyId()));
+		if(table == null){
+			return;
+		}
+		String tableName = table.getInitTableName();
+		if(StringUtils.isEmpty(tableName)){
+			return;
+		}
+
+		//获取首件记录ID
+		String firstId = tableInfoList.get(0).getFirstId();
+		if(StringUtils.isNotEmpty(firstId)){
+			//删除掉旧数据
+			this.jdbcTemplate.execute("DELETE FROM " + tableName + " WHERE group_id = " + firstId);
+		} else {
+			firstId = SnowFlakeUtil.getId() + "";
+		}
+		//新增数据
+		for(TableInfo tableInfo : tableInfoList){
+			//获取字段信息
+			LinkedHashMap<String,String> dataMap2 = tableInfo.getDataMap();
+
+			//拼接SQL
+			StringBuilder sql = new StringBuilder("INSERT INTO " + tableName ),
+					keySql = new StringBuilder("id, group_id"),
+					valSql = new StringBuilder("" + SnowFlakeUtil.getId() + ", " + firstId);
+
+			for(String key : dataMap2.keySet()){
+				keySql.append(", ").append(key);
+				valSql.append(", '").append(dataMap2.get(key)).append("'");
+			}
+
+			sql.append("(").append(keySql).append(")").append(" values(").append(valSql).append(")");
+
+			//新增数据
+			try{
+				this.jdbcTemplate.execute(sql.toString());
+			}catch (Exception e){
+				e.printStackTrace();
+			}
+		}
+
+		try{
+			//新增或修改首件记录
+			this.informationQueryClient.saveOrUpdateInformationQueryData(firstNodeId, tableInfoList.get(0).getPkeyId() + "", firstId, "文件名称", Integer.parseInt(tableInfoList.get(0).getClassify()), 2, "true", linkProcessList);
+		}catch (Exception e){
+			e.printStackTrace();
+		}
+
+	}
+
 	@Override
 	public void saveOrUpdateInfo(List<TableInfo> tableInfoList) {
 		if(ListUtils.isNotEmpty(tableInfoList)){
-			if(StringUtils.isNotEmpty(tableInfoList.get(0).getIsTheLog())){
+			if(StringUtils.isNotEmpty(tableInfoList.get(0).getIsFirst())){
+				//首件填报
+				this.saveOrUpdateFirst(tableInfoList);
+
+			} else if(StringUtils.isNotEmpty(tableInfoList.get(0).getIsTheLog())){
 				//日志填报
 				this.saveOrUpdateTheLog(tableInfoList);
 
@@ -423,7 +512,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 					fileName = StringUtils.isNotEmpty(fileName) ? fileName : "缺少文件提名配置";
 
 					//huangjn 保存成功后调用生成资料查询列表数据
-					this.informationQueryClient.saveOrUpdateInformationQueryData(wbsTreeContractByP.getPKeyId()+"", "业务ID(主要将来给首件使用)", fileName, Integer.parseInt(tableInfo.getClassify()), 2,"是否是首件(临时,暂时没用到)");
+					this.informationQueryClient.saveOrUpdateInformationQueryData(wbsTreeContractByP.getPKeyId()+"", "首件使用字段", "业务ID(主要将来给首件使用)", fileName, Integer.parseInt(tableInfo.getClassify()), 2,"是否是首件(临时,暂时没用到)", new ArrayList<>());
 				}
 
 				UpdateWrapper<WbsTreeContract> updateWrapper = new UpdateWrapper<>();
@@ -447,7 +536,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 					fileName = StringUtils.isNotEmpty(fileName) ? fileName : "缺少文件提名配置";
 
 					//huangjn 保存成功后调用生成资料查询列表数据
-					this.informationQueryClient.saveOrUpdateInformationQueryData(wbsTreeContractByP.getPKeyId()+"", "业务ID(主要将来给首件使用)", fileName, Integer.parseInt(tableInfoList.get(0).getClassify()), 2,"是否是首件(临时,暂时没用到)");
+					this.informationQueryClient.saveOrUpdateInformationQueryData(wbsTreeContractByP.getPKeyId()+"", "首件使用字段", "业务ID(主要将来给首件使用)", fileName, Integer.parseInt(tableInfoList.get(0).getClassify()), 2,"false", new ArrayList<>());
 				}catch (Exception e){
 					e.printStackTrace();
 				}