Commit a8485a2a authored by danfuman's avatar danfuman

Merge branch 'V20231129-中建一局二公司' of http://192.168.60.201/root/dsk-operate-sys...

Merge branch 'V20231129-中建一局二公司' of http://192.168.60.201/root/dsk-operate-sys into V20231129-中建一局二公司
parents 61ec6262 0a8d6205
......@@ -8,10 +8,14 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 异步配置
......@@ -22,16 +26,56 @@ import java.util.concurrent.ScheduledExecutorService;
@Configuration
public class AsyncConfig extends AsyncConfigurerSupport {
@Autowired
@Qualifier("scheduledExecutorService")
private ScheduledExecutorService scheduledExecutorService;
// @Autowired
// @Qualifier("scheduledExecutorService")
// private ScheduledExecutorService scheduledExecutorService;
//
// /**
// * 自定义 @Async 注解使用系统线程池
// */
// @Override
// public Executor getAsyncExecutor() {
// return scheduledExecutorService;
// }
/**
* 自定义 @Async 注解使用系统线程池
*/
@Override
public Executor getAsyncExecutor() {
return scheduledExecutorService;
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 核心线程数:线程池创建时候初始化的线程数
taskExecutor.setCorePoolSize(10);
// 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
taskExecutor.setMaxPoolSize(20);
// 缓冲队列:用来缓冲执行任务的队列
taskExecutor.setQueueCapacity(50);
// 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁
taskExecutor.setKeepAliveSeconds(60);
// 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
taskExecutor.setThreadNamePrefix("HiTask-");
// 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程)
//taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
taskExecutor.initialize();
//解决使用@Async注解,获取不到上下文信息的问题
taskExecutor.setTaskDecorator(runnable -> {
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
return ()->{
try {
// 我们set 进去 ,其实是一个ThreadLocal维护的.
RequestContextHolder.setRequestAttributes(requestAttributes);
runnable.run();
} finally {
// 最后记得释放内存
RequestContextHolder.resetRequestAttributes();
}
};
});
return taskExecutor;
}
/**
......
package com.dsk.component;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dsk.common.excel.ExcelUtils;
import com.dsk.common.exception.ServiceException;
import com.dsk.cscec.constant.CbProjectConstants;
import com.dsk.cscec.domain.CbProjectFile;
import com.dsk.cscec.domain.CbProjectOther;
import com.dsk.cscec.domain.bo.CbProjectBaseBo;
import com.dsk.cscec.service.CbProjectFileService;
import com.dsk.cscec.service.CbProjectOtherService;
import com.dsk.system.service.ISysOssService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 其他费用数据解析组件
*
* @Author lcl
* @Data 2024/2/7 17:43
*/
@Slf4j
@Component
public class CbProjectOtherAnalysisComponent {
@Resource
private CbProjectOtherService projectOtherService;
@Resource
private CbProjectFileService projectFileService;
@Resource
private ISysOssService ossService;
@Resource
private TransactionTemplate transactionTemplate;
/**
* 其他费用数据解析
*/
@Async
public void projectOtherDataAnalysis(CbProjectBaseBo bo) throws Exception {
//查询其他费用导入文件
List<CbProjectFile> fileList = projectFileService.list(Wrappers.<CbProjectFile>lambdaQuery()
.eq(CbProjectFile::getProjectId, bo.getProjectId())
.eq(CbProjectFile::getCbType, CbProjectConstants.CB_TYPE_OTHER_PROJECT)
.eq(CbProjectFile::getCbStage, bo.getCbStage())
.in(CbProjectFile::getFileParseStatus, Arrays.asList(1, 3)));
if (ObjectUtils.isEmpty(fileList)) {
return;
}
//文件处理
for (CbProjectFile file : fileList) {
if (file.getDelFlag() == 0) {
//文件下载
InputStream inputStream = ossService.downFileIO(file.getFileOssId());
if (ObjectUtil.isNull(inputStream)) {
file.setFileParseStatus(3);
file.setFailRemark("文件数据不存在");
projectFileService.updateById(file);
break;
}
//解析数据
List<CbProjectOther> importList = new ExcelUtils<>(CbProjectOther.class).importExcelAllSheet(inputStream, 1);
if (importList.isEmpty()) {
file.setFileParseStatus(3);
file.setFailRemark("表格中不存在待导入数据!");
projectFileService.updateById(file);
break;
}
List<CbProjectOther> projectOtherList = importList.stream().parallel()
.peek(item -> {
item.setProjectId(bo.getProjectId());
item.setCbStage(bo.getCbStage());
item.setCbProjectFileId(file.getId());
}).collect(Collectors.toList());
if (projectOtherList.isEmpty()) {
throw new ServiceException("表格中不存在有效数据数据!");
}
transactionTemplate.execute(status -> {
try {
//分批次插入
if (projectOtherList.size() > 1000) {
int index = 0;
int sum = projectOtherList.size();
while (index < sum) {
List<CbProjectOther> divideList = projectOtherList.subList(index, Math.max((index + 1) * 1000, sum));
boolean b = projectOtherService.saveBatch(divideList);
if (!b) {
throw new ServiceException("数据插入失败!");
}
index += 1000;
}
} else {
boolean b = projectOtherService.saveBatch(projectOtherList);
if (!b) {
throw new ServiceException("数据插入失败!");
}
}
file.setFileParseStatus(2);
boolean b = projectFileService.updateById(file);
if (!b) {
throw new ServiceException("文件状态更新失败!");
}
} catch (Exception e) {
status.setRollbackOnly();
file.setFileParseStatus(3);
file.setFailRemark(e.getMessage());
projectFileService.updateById(file);
}
return Boolean.TRUE;
});
} else {
projectOtherService.remove(Wrappers.<CbProjectOther>lambdaQuery().eq(CbProjectOther::getCbProjectFileId, file.getId()));
projectFileService.removeById(file);
}
}
}
}
......@@ -50,11 +50,7 @@ public class DataAnalysisComponent {
@Async
public void quantitySummaryDataAnalysis(CbProjectBaseBo bo) throws Exception {
//查询工料汇总导入文件
List<CbProjectFile> fileList = projectFileService.list(Wrappers.<CbProjectFile>lambdaQuery()
.eq(CbProjectFile::getProjectId, bo.getProjectId())
.eq(CbProjectFile::getCbType, CbProjectConstants.CB_TYPE_QUANTITY_SUMMARY)
.eq(CbProjectFile::getCbStage, bo.getCbStage())
.in(CbProjectFile::getFileParseStatus, Arrays.asList(1, 3)));
List<CbProjectFile> fileList = projectFileService.selectAnalysisList(bo.getProjectId(), CbProjectConstants.CB_TYPE_QUANTITY_SUMMARY, bo.getCbStage());
if (ObjectUtils.isEmpty(fileList)) return;
//文件处理
for (CbProjectFile file : fileList) {
......
package com.dsk.cscec.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dsk.common.annotation.Log;
import com.dsk.common.core.domain.R;
import com.dsk.common.enums.BusinessType;
import com.dsk.component.CbProjectOtherAnalysisComponent;
import com.dsk.cscec.domain.CbProjectExpenseSummary;
import com.dsk.cscec.domain.bo.CbProjectBaseBo;
import com.dsk.cscec.domain.bo.CbProjectOtherBo;
import com.dsk.cscec.domain.vo.CbProjectOtherVo;
import com.dsk.cscec.service.CbProjectExpenseSummaryService;
import com.dsk.cscec.service.CbProjectOtherService;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @ClassName CbProjectOtherController
* @Description 其他费用相关控制器
* @Author Dgm
* @Date 2024/2/8 10:55
* @Version 1.0.0
*/
@RestController
@RequestMapping("cb/projectOther")
public class CbProjectOtherController {
@Resource
private CbProjectOtherService projectOtherService;
@Resource
private CbProjectExpenseSummaryService cbProjectExpenseSummaryService;
@Resource
private CbProjectOtherAnalysisComponent otherAnalysisComponent;
@GetMapping(value = "/projectOther/dataAnalysis")
public R<List<CbProjectExpenseSummary>> projectOtherDataAnalysis(CbProjectBaseBo baseBo) throws Exception{
otherAnalysisComponent.projectOtherDataAnalysis(baseBo);
return R.ok();
}
/***
* @Description: 其他费用-汇总
* @Param:
* @return: com.dsk.common.core.domain.R<java.util.List<com.dsk.cscec.domain.vo.CbProjectOtherVo>>
* @Author: Dgm
* @date: 2024/2/8 14:08
*/
@SaIgnore
@GetMapping(value = "/statistics/{projectId}")
public R<List<CbProjectExpenseSummary>> statistics(@PathVariable Long projectId) {
CbProjectExpenseSummary expenseSummary = new CbProjectExpenseSummary();
expenseSummary.setProjectId(projectId);
expenseSummary.setDataType(2);
QueryWrapper<CbProjectExpenseSummary> queryWrapper = Wrappers.query(expenseSummary);
queryWrapper.select("id","expense_name as expenseName","expense_value as expenseValue");
queryWrapper.orderByAsc("id");
List<CbProjectExpenseSummary> expenseSummaryList = this.cbProjectExpenseSummaryService.list(queryWrapper);
if (ObjectUtil.isEmpty(expenseSummaryList)) {
expenseSummaryList = new ArrayList<>();
}
return R.ok(expenseSummaryList);
}
/***
* @Description: 其他费用一级大类
* @Param:
* @return: com.dsk.common.core.domain.R<java.util.List<com.dsk.cscec.domain.vo.CbProjectOtherVo>>
* @Author: Dgm
* @date: 2024/2/8 14:08
*/
@SaIgnore
@GetMapping(value = "/type/{projectId}")
public R<List<Map<String, Object>>> dictType(@PathVariable Long projectId) {
List<Map<String, Object>> data = projectOtherService.listByLevel(projectId,0);
if (ObjectUtil.isNull(data)) {
data = new ArrayList<>();
}
return R.ok(data);
}
/***
* @Description: 其他费用列表
* @Param:
* @return: com.dsk.common.core.domain.R<java.util.List<com.dsk.cscec.domain.vo.CbProjectOtherVo>>
* @Author: Dgm
* @date: 2024/2/8 14:08
*/
@SaIgnore
@GetMapping("/list")
public R<List<CbProjectOtherVo>> list(CbProjectOtherBo projectOtherBo) {
List<CbProjectOtherVo> data= projectOtherService.selectDataList(projectOtherBo);
if (ObjectUtil.isNull(data)) {
data = new ArrayList<>();
}
return R.ok(data);
}
/***
* @Description: 其他费用-导入数据
* @param file 导入文件
* @param projectId 项目id
* @return: com.dsk.common.core.domain.R<java.util.List<com.dsk.cscec.domain.vo.CbProjectOtherVo>>
* @Author: Dgm
* @date: 2024/2/8 14:08
*/
@Log(title = "其他费用相关项导入", businessType = BusinessType.IMPORT)
@PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<Void> importData(@RequestPart("file") MultipartFile file, Long projectId) throws Exception {
projectOtherService.importExcelData(file,projectId);
return R.ok();
}
}
......@@ -67,7 +67,7 @@ public class CbProjectRecordController extends BaseController {
* 获取项目台账列表
*/
@GetMapping("/getProjectList")
public TableDataInfo<CbProjectRecordSearchVo> getProjectList(@RequestBody CbProjectSearchBo searchBo, PageQuery pageQuery) {
public TableDataInfo<CbProjectRecordSearchVo> getProjectList(CbProjectSearchBo searchBo, PageQuery pageQuery) {
return baseService.getProjectList(searchBo, pageQuery);
}
......
......@@ -134,7 +134,7 @@ public class CbSummaryController extends BaseController {
*/
@PostMapping("/analysisData")
public void analysisData(Long projectId){
cbSummaryService.importCbProject(projectId);
cbSummaryService.importCbSummary(projectId);
}
}
package com.dsk.cscec.domain;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @ClassName CbProjectOtherVo
* @Description 项目其他项目费用
* @Author Dgm
* @Date 2024/2/8 10:39
* @Version 1.0.0
*/
@Data
public class CbProjectOther implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
private Long id;
/**
* 成本阶段( 0:标前成本、1:标后成本、2:转固成本)
*/
private Integer cbStage;
/**
* 项目ID
*/
private Long projectId;
/**
* 父项id
*/
private Long parentId;
/**
* 序号
*/
private String number;
/**
* 处理后序号
*/
private String dealWithNumber;
/**
* 清单内容
*/
private String itemContent;
/**
* 工作内容、做法/规格型号/施工现场配置说明
*/
private String workContent;
/**
* 单位
*/
private String unit;
/**
* 工程量
*/
private BigDecimal engineeringQuantity;
/**
* 不含税单价
*/
private String unitPriceExcludingTax;
/**
* 不含税合价
*/
private String totalPriceExcludeTax;
/**
* 税率(%)
*/
private String taxRate;
/**
* 含税合价
*/
private String totalPriceIncludingTax;
/**
* 税金(元)
*/
private String taxAmount;
/**
* 成本科目
*/
private String costSubject;
/**
* 税金类型
*/
private String taxType;
/**
* 数据类型(1:履约担保、保函手续费、市场营销奖励费、2:创优费:3:其他:4:保险保函:5:水电费:6:现场其他直接费:7:技术质量管理:8:工程保险类:10:报批报建、竣工验收类
*/
private String dataType;
/**
* 备注
*/
private String remarks;
/**
* 修改人
*/
private String updateBy;
/**
* 创建人
*/
private String createBy;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 项目成本文件id
*/
private Long cbProjectFileId;
}
......@@ -44,9 +44,9 @@ public class CbProjectRecord extends BaseEntity implements Serializable {
*/
private String ipmProjectNo;
/**
* 是否获取项目详情(0:是、1:否)
* 是否获取项目详情
*/
private Integer isGetProjectDetail;
private Boolean isGetProjectDetail;
/**
* 文件名称
*/
......
......@@ -48,10 +48,7 @@ public class CbQuantitySummaryActual implements Serializable {
* 采购单价
*/
private Double purchaseUnitPrice;
/**
* 创建时间
*/
private Date createTime;
/**
* 推送时间
*/
......@@ -76,6 +73,18 @@ public class CbQuantitySummaryActual implements Serializable {
* IPM作业编码
*/
private String ipmBizCode;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新人
*/
private String updateBy;
/**
* 更新时间
*/
private Date updateTime;
}
......@@ -20,10 +20,10 @@ public class AddCbProjectBo {
*/
private String ipmProjectNo;
/**
* 是否获取项目详情(0:否、1:是)
* 是否获取项目详情
*/
@NotNull(message = "是否获取项目详情不能为空")
private Integer isGetProjectDetail;
private Boolean isGetProjectDetail;
/**
* 文件名称
*/
......
package com.dsk.cscec.domain.bo;
import lombok.Data;
@Data
public class CbProjectOtherBo {
/**
* 费用项Id
*/
private Long parentId;
/**
* 年月
*/
private String month;
/**
* 项目id
*/
private Long projectId;
/**
* 成本阶段( 0:标前成本、1:标后成本、2:转固成本)
*/
private Integer cbStage;
}
\ No newline at end of file
......@@ -25,10 +25,10 @@ public class EditProjectInfoBo {
*/
private String ipmProjectNo;
/**
* 是否获取项目详情(0:否、1:是)
* 是否获取项目详情
*/
@NotNull(message = "是否获取项目详情不能为空")
private Integer isGetProjectDetail;
private Boolean isGetProjectDetail;
/**
* 文件名称
*/
......
package com.dsk.cscec.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* @ClassName CbProjectOtherVo
* @Description 项目其他项目费用
* @Author Dgm
* @Date 2024/2/8 10:39
* @Version 1.0.0
*/
@Data
public class CbProjectOtherImportVo {
/**
* 序号
*/
@ExcelProperty(value = "序号")
private String number;
/**
* 清单内容
*/
@ExcelProperty(value = "清单内容")
private String itemContent;
/**
* 工作内容、做法/规格型号/施工现场配置说明
*/
@ExcelProperty(value = "工作内容")
private String workContent;
/**
* 单位
*/
@ExcelProperty(value = "单位")
private String unit;
/**
* 工程量
*/
@ExcelProperty(value = "工程量")
private BigDecimal engineeringQuantity;
/**
* 不含税单价
*/
@ExcelProperty(value = "不含税单价")
private String unitPriceExcludingTax;
/**
* 不含税合价
*/
@ExcelProperty(value = "不含税合价")
private String totalPriceExcludeTax;
/**
* 税率(%)
*/
@ExcelProperty(value = "税率(%)")
private String taxRate;
/**
* 含税合价
*/
@ExcelProperty(value = "含税合价")
private String totalPriceIncludingTax;
/**
* 税金(元)
*/
@ExcelProperty(value = "税金(元)")
private String taxAmount;
/**
* 成本科目
*/
@ExcelProperty(value = "成本科目")
private String costSubject;
/**
* 税金类型
*/
@ExcelProperty(value = "税金类型")
private String taxType;
/**
* 备注
*/
@ExcelProperty(value = "备注")
private String remarks;
/**
* 数据类型(1:履约担保、保函手续费、市场营销奖励费、2:创优费:3:其他:4:保险保函:5:水电费:6:现场其他直接费:7:技术质量管理:8:工程保险类:10:报批报建、竣工验收类
*/
private String dataType;
/**
* 主键id
*/
private Long id;
/**
* 成本阶段( 0:标前成本、1:标后成本、2:转固成本)
*/
private Integer cbStage;
/**
* 项目ID
*/
private Long projectId;
/**
* 父项id
*/
private Long parentId;
/**
* 处理后序号
*/
private String dealWithNumber;
}
package com.dsk.cscec.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* @ClassName CbProjectOtherVo
* @Description 项目其他项目费用
* @Author Dgm
* @Date 2024/2/8 10:39
* @Version 1.0.0
*/
@Data
public class CbProjectOtherVo {
/**
* 主键id
*/
private Long id;
/**
* 成本阶段( 0:标前成本、1:标后成本、2:转固成本)
*/
private Integer cbStage;
/**
* 项目ID
*/
private Long projectId;
/**
* 父项id
*/
private Long parentId;
/**
* 序号
*/
private String number;
/**
* 处理后序号
*/
private String dealWithNumber;
/**
* 清单内容
*/
private String itemContent;
/**
* 工作内容、做法/规格型号/施工现场配置说明
*/
private String workContent;
/**
* 单位
*/
private String unit;
/**
* 工程量
*/
private BigDecimal engineeringQuantity;
/**
* 不含税单价
*/
private String unitPriceExcludingTax;
/**
* 不含税合价
*/
private String totalPriceExcludeTax;
/**
* 税率(%)
*/
private String taxRate;
/**
* 含税合价
*/
private String totalPriceIncludingTax;
/**
* 税金(元)
*/
private String taxAmount;
/**
* 成本科目
*/
private String costSubject;
/**
* 税金类型
*/
private String taxType;
/**
* 数据类型(1:履约担保、保函手续费、市场营销奖励费、2:创优费:3:其他:4:保险保函:5:水电费:6:现场其他直接费:7:技术质量管理:8:工程保险类:10:报批报建、竣工验收类
*/
private String dataType;
/**
* 备注
*/
private String remarks;
/**
* 修改人
*/
private String updateBy;
/**
* 创建人
*/
private String createBy;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
......@@ -88,4 +88,9 @@ public class CbSummaryActualListVo extends BaseEntity {
private String expenseDate;
private List<CbSummaryActualListVo> children;
/**
* 是否有子级(0否1是)
*/
private Integer hasChildren;
}
package com.dsk.cscec.listener;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.dsk.common.excel.ExcelListener;
import com.dsk.common.excel.ExcelResult;
import com.dsk.common.exception.ServiceException;
import com.dsk.cscec.domain.vo.CbProjectExpenseSummaryImportVo;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
/**
* 其他项目自定义导入
*
* @author Lion Li
*/
@Slf4j
public class CbProjectExpenseSummaryImportListener extends AnalysisEventListener<CbProjectExpenseSummaryImportVo> implements ExcelListener<CbProjectExpenseSummaryImportVo> {
private final Long projectId;
private final Integer cbStage;
private List<CbProjectExpenseSummaryImportVo> dataList = new ArrayList<>();
private int successNum = 0;
private int failureNum = 0;
private final StringBuilder successMsg = new StringBuilder();
private final StringBuilder failureMsg = new StringBuilder();
public CbProjectExpenseSummaryImportListener(Long projectId, Integer cbStage) {
this.cbStage = cbStage;
this.projectId = projectId;
}
@Override
public void invoke(CbProjectExpenseSummaryImportVo importVo, AnalysisContext context) {
Integer rowIndex = context.readRowHolder().getRowIndex();
if (StrUtil.isEmpty(importVo.getExpenseName())) {
failureNum++;
failureMsg.append("<br/>" + rowIndex + "行 解析失败:清单内容不能为空");
}
String number = importVo.getNumber();
if (StrUtil.isEmpty(number)) {
failureNum++;
failureMsg.append("<br/>" + rowIndex + "行 解析失败:序号不能为空");
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
@Override
public ExcelResult<CbProjectExpenseSummaryImportVo> getExcelResult() {
return new ExcelResult<CbProjectExpenseSummaryImportVo>() {
@Override
public String getAnalysis() {
if (failureNum > 0) {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new ServiceException(failureMsg.toString());
} else {
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
}
return successMsg.toString();
}
@Override
public List<CbProjectExpenseSummaryImportVo> getList() {
return dataList;
}
@Override
public List<String> getErrorList() {
return null;
}
};
}
}
package com.dsk.cscec.listener;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.dsk.common.excel.ExcelListener;
import com.dsk.common.excel.ExcelResult;
import com.dsk.common.exception.ServiceException;
import com.dsk.cscec.domain.vo.CbProjectOtherImportVo;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* 其他项目自定义导入
*
* @author Lion Li
*/
@Slf4j
public class CbProjectOtherImportListener extends AnalysisEventListener<CbProjectOtherImportVo> implements ExcelListener<CbProjectOtherImportVo> {
private final Long projectId;
private final Integer cbStage;
private List<CbProjectOtherImportVo> dataList = new ArrayList<>();
private int successNum = 0;
private int failureNum = 0;
private final StringBuilder successMsg = new StringBuilder();
private final StringBuilder failureMsg = new StringBuilder();
public CbProjectOtherImportListener(Long projectId, Integer cbStage) {
this.cbStage = cbStage;
this.projectId = projectId;
}
@Override
public void invoke(CbProjectOtherImportVo importVo, AnalysisContext context) {
Integer rowIndex = context.readRowHolder().getRowIndex();
if (StrUtil.isEmpty(importVo.getItemContent())) {
failureNum++;
failureMsg.append("<br/>" + rowIndex + "行 解析失败:清单内容不能为空");
}
String number = importVo.getNumber();
if (StrUtil.isEmpty(number)) {
failureNum++;
failureMsg.append("<br/>" + rowIndex + "行 解析失败:序号不能为空");
}
Boolean numberMatch = false;
String regex = "[\\((]*[一|二|三|四|五|六|七|八|九|十]+[\\))]*";
Pattern pattern = Pattern.compile("^\\d+(\\.\\d+)*$");
Pattern pattern3 = Pattern.compile("^([1-9][0-9]*|0)$");
if (ReUtil.isMatch(regex, number) || ReUtil.isMatch(pattern, number)||ReUtil.isMatch(pattern3, number)) {
numberMatch = true;
} else {
failureNum++;
failureMsg.append("<br/>" + rowIndex + "行 解析失败:序号格式错误");
}
if(numberMatch){
if (ReUtil.isMatch(regex, number)){
String replace = number.replaceAll("[\\\\((]|[\\\\))]", "");
int no = Convert.chineseToNumber(replace);
importVo.setDealWithNumber(String.valueOf(no));
}else{
importVo.setDealWithNumber(importVo.getNumber());
}
dataList.add(importVo);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
@Override
public ExcelResult<CbProjectOtherImportVo> getExcelResult() {
return new ExcelResult<CbProjectOtherImportVo>() {
@Override
public String getAnalysis() {
if (failureNum > 0) {
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new ServiceException(failureMsg.toString());
} else {
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
}
return successMsg.toString();
}
@Override
public List<CbProjectOtherImportVo> getList() {
return dataList;
}
@Override
public List<String> getErrorList() {
return null;
}
};
}
}
......@@ -53,6 +53,12 @@ public class CbSummaryCostAccountImportListener extends AnalysisEventListener<Cb
failureMsg.append("<br/>").append("第" + sort + "条数据序号为空");
return;
}
//成本科目不能为空
if (StringUtil.isBlank(importVo.getCbName())) {
failureNum++;
failureMsg.append("<br/>").append("第" + sort + "条数据成本科目为空");
return;
}
//父级数据处理
if (sort == 1) {
......@@ -74,7 +80,7 @@ public class CbSummaryCostAccountImportListener extends AnalysisEventListener<Cb
@Override
public String getAnalysis() {
if (failureNum > 0) {
failureMsg.insert(0, "失败原因:共 " + failureNum + " 条数据格式不正确,错误如下:");
failureMsg.insert(0, "共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new ServiceException(failureMsg.toString());
} else {
successMsg.insert(0, "成本科目汇总数据已全部解析成功!共 " + getList().size() + " 条");
......
package com.dsk.cscec.listener;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.dsk.common.excel.ExcelListener;
......@@ -42,8 +43,12 @@ public class CbSummaryProjectImportListener extends AnalysisEventListener<CbSumm
@Override
public void invoke(CbSummaryProjectImportVo importVo, AnalysisContext context) {
//第一个序号不能为空? todo
//名称不能为空
if (StringUtil.isBlank(importVo.getCbName())) {
failureNum++;
failureMsg.append("<br/>").append("第" + sort + "条数据名称为空");
return;
}
//添加父级数据
if (sort == 0) {
CbSummaryProjectImportVo firstVo = new CbSummaryProjectImportVo();
......@@ -63,8 +68,12 @@ public class CbSummaryProjectImportListener extends AnalysisEventListener<CbSumm
//按sort倒序取number不为空的最大level
Object[] objects = resultList.stream().sorted(Comparator.comparingInt(CbSummaryProjectImportVo::getSort).reversed())
.filter(vo -> StringUtil.isNotBlank(vo.getNumber())).limit(1).map(CbSummaryProjectImportVo::getLevel).toArray();
//数据序号错误 todo
//数据序号错误
if (ObjectUtil.isEmpty(objects)) {
failureNum++;
failureMsg.append("<br/>").append("第" + sort + "条数据序号错误");
return;
}
Integer lastLevel = (Integer) objects[0];
importVo.setLevel(lastLevel + 1);
......@@ -75,8 +84,6 @@ public class CbSummaryProjectImportListener extends AnalysisEventListener<CbSumm
}
// failureNum++;
// failureMsg.append("<br/>").append(failureNum);
resultList.add(importVo);
}
......@@ -93,7 +100,7 @@ public class CbSummaryProjectImportListener extends AnalysisEventListener<CbSumm
@Override
public String getAnalysis() {
if (failureNum > 0) {
failureMsg.insert(0, "失败原因:共 " + failureNum + " 条数据格式不正确,错误如下:");
failureMsg.insert(0, "共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new ServiceException(failureMsg.toString());
} else {
successMsg.insert(0, "项目汇总数据已全部解析成功!共 " + getList().size() + " 条");
......
......@@ -2,6 +2,9 @@ package com.dsk.cscec.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsk.cscec.domain.CbProjectFile;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 项目成本文件表(CbProjectFile)表数据库访问层
......@@ -11,5 +14,8 @@ import com.dsk.cscec.domain.CbProjectFile;
*/
public interface CbProjectFileMapper extends BaseMapper<CbProjectFile> {
List<CbProjectFile> selectAnalysisList(@Param("projectId") Long projectId,@Param("cbType") Integer cbType,@Param("cbStage") Integer cbStage);
int removeById(@Param("id") Long id);
}
package com.dsk.cscec.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dsk.cscec.domain.CbProjectOther;
import com.dsk.cscec.domain.bo.CbProjectOtherBo;
import com.dsk.cscec.domain.vo.CbProjectOtherVo;
import java.util.List;
public interface CbProjectOtherMapper extends BaseMapper<CbProjectOther> {
List<CbProjectOtherVo> selectListByProjectAndStage(CbProjectOtherBo projectOtherBo);
}
\ No newline at end of file
......@@ -6,6 +6,8 @@ import com.dsk.cscec.domain.bo.AddProjectFileUploadBo;
import com.dsk.cscec.domain.vo.QueryProjectFileUploadDetailVo;
import com.dsk.system.domain.vo.SysOssVo;
import java.util.List;
/**
* 项目成本文件表(CbProjectFile)表服务接口
*
......@@ -44,4 +46,14 @@ public interface CbProjectFileService extends IService<CbProjectFile> {
* @return 文件列表
*/
QueryProjectFileUploadDetailVo getProjectFileUploadDetail(Long projectId);
/**
* 查询项目文件解析列表
* @param projectId 项目ID
* @param cbType 成本类型(0:直接费成本、1:工料汇总、2:措施项目、3:其他项目、4:现场经费、5:成本汇总)
* @param cbStage 成本阶段(0:标前成本、1:标后成本、2:转固成本)
* @return
*/
List<CbProjectFile> selectAnalysisList(Long projectId, Integer cbType, Integer cbStage);
}
package com.dsk.cscec.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsk.cscec.domain.CbProjectOther;
import com.dsk.cscec.domain.bo.CbProjectOtherBo;
import com.dsk.cscec.domain.vo.CbProjectOtherVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* 成本-工料汇总基本表(CbQuantitySummary)表服务接口
*
* @author lcl
* @since 2024-02-05 11:06:56
*/
public interface CbProjectOtherService extends IService<CbProjectOther> {
void importExcelData(MultipartFile file, Long projectId);
List<Map<String, Object>> listByLevel(Long projectId, int i);
List<CbProjectOtherVo> selectDataList(CbProjectOtherBo projectOtherBo);
}
......@@ -2,7 +2,6 @@ package com.dsk.cscec.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dsk.common.core.domain.R;
import com.dsk.cscec.domain.CbProjectFile;
import com.dsk.cscec.domain.CbSummary;
import com.dsk.cscec.domain.bo.CbSummaryActualBo;
import com.dsk.cscec.domain.bo.CbSummaryActualListBo;
......@@ -23,10 +22,10 @@ import java.util.Map;
public interface CbSummaryService extends IService<CbSummary> {
/**
* 项目汇总导入
* 成本汇总导入
* @param projectId
*/
void importCbProject(Long projectId);
void importCbSummary(Long projectId);
/**
* 获取一级名称/成本科目列表
......
......@@ -162,6 +162,11 @@ public class CbProjectFileServiceImpl extends ServiceImpl<CbProjectFileMapper, C
return draftDetailVo;
}
@Override
public List<CbProjectFile> selectAnalysisList(Long projectId, Integer cbType, Integer cbStage) {
return baseMapper.selectAnalysisList(projectId, cbType, cbStage);
}
/**
* 校验项目是否存在
*
......
package com.dsk.cscec.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsk.common.excel.ExcelResult;
import com.dsk.common.excel.ExcelUtils;
import com.dsk.common.utils.poi.ExcelUtil;
import com.dsk.cscec.constant.CbProjectConstants;
import com.dsk.cscec.domain.*;
import com.dsk.cscec.domain.bo.CbProjectBaseBo;
import com.dsk.cscec.domain.bo.CbProjectOtherBo;
import com.dsk.cscec.domain.vo.CbProjectExpenseSummaryImportVo;
import com.dsk.cscec.domain.vo.CbProjectOtherImportVo;
import com.dsk.cscec.domain.vo.CbProjectOtherVo;
import com.dsk.cscec.listener.CbProjectExpenseSummaryImportListener;
import com.dsk.cscec.listener.CbProjectOtherImportListener;
import com.dsk.cscec.mapper.CbProjectOtherMapper;
import com.dsk.cscec.service.*;
import com.dsk.system.service.ISysOssService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.regex.Pattern;
@Slf4j
@Service
public class CbProjectOtherServiceImpl extends ServiceImpl<CbProjectOtherMapper, CbProjectOther> implements CbProjectOtherService {
private final String firstPattern = "[\\((]*[一|二|三|四|五|六|七|八|九|十]+[\\))]*";
private final Pattern secondPattern = Pattern.compile("^\\d+(\\.\\d+)*$");
private final Pattern pattern3 = Pattern.compile("^([1-9][0-9]*|0)$");
@Resource
private CbProjectRecordService cbProjectRecordService;
@Resource
private CbProjectFileService projectFileService;
@Resource
private ISysOssService ossService;
@Resource
private CbProjectExpenseSummaryService projectExpenseSummaryService;
@SneakyThrows
@Override
public void importExcelData(MultipartFile file, Long projectId) {
String name = file.getOriginalFilename();
name = FileNameUtil.getPrefix(name);
CbProjectRecord byId = cbProjectRecordService.getById(projectId);
Assert.notNull(byId, "项目信息不能为空");
Integer cbStage = byId.getCbStage();
CbProjectOtherImportListener importListener = new CbProjectOtherImportListener(projectId, cbStage);
EasyExcel.read(file.getInputStream(), CbProjectOtherImportVo.class, importListener).sheet().doRead();
ExcelResult<CbProjectOtherImportVo> result = importListener.getExcelResult();
String analysis = result.getAnalysis();
List<CbProjectOtherImportVo> list = result.getList();
if (CollectionUtil.isEmpty(list)) {
//解析失败
log.debug(">>>>解析失败" + list.size());
//todo 解析失败更新文件备注
return;
}
log.debug(">>>>" + list.size());
CbProjectOther rootProjectOther = new CbProjectOther();
rootProjectOther.setItemContent(name);
rootProjectOther.setParentId(0L);
rootProjectOther.setProjectId(projectId);
rootProjectOther.setCbStage(cbStage);
LambdaQueryWrapper<CbProjectOther> tWrapper = Wrappers.lambdaQuery(rootProjectOther);
CbProjectOther rootOther = this.getOne(tWrapper);
if (ObjectUtil.isEmpty(rootOther)) {
this.save(rootProjectOther);
rootProjectOther.setDealWithNumber(String.valueOf(rootProjectOther.getId()));
this.updateById(rootProjectOther);
}
Long rootMeasuresId = rootProjectOther.getId();
if (CollectionUtil.isNotEmpty(list)) {
for (CbProjectOtherImportVo importVo : list) {
String number = importVo.getNumber();
CbProjectOther cbProjectOther = new CbProjectOther();
//保存一级节点
if (ReUtil.isMatch(firstPattern, number) || ReUtil.isMatch(pattern3, number)) {
BeanUtil.copyProperties(importVo, cbProjectOther);
cbProjectOther.setParentId(rootMeasuresId);
// cbProjectOther.setLevel(1);
} else if (ReUtil.isMatch(secondPattern, number)) {
BeanUtil.copyProperties(importVo, cbProjectOther);
// 根据no查询父级节点
CbProjectOther parentCbCostMeasure = getCbProjectOther(rootMeasuresId, number, projectId, cbStage);
String[] split = number.split("\\.");
// cbProjectOther.setLevel(split.length);
cbProjectOther.setParentId(parentCbCostMeasure.getId());
}
String newNo = String.valueOf(rootMeasuresId).concat(".").concat(cbProjectOther.getDealWithNumber());
cbProjectOther.setDealWithNumber(newNo);
cbProjectOther.setProjectId(projectId);
cbProjectOther.setCbStage(cbStage);
this.save(cbProjectOther);
}
}
}
@Override
public List<Map<String, Object>> listByLevel(Long projectId, int i) {
CbProjectRecord byId = cbProjectRecordService.getById(projectId);
Assert.notNull(byId, "项目信息不能为空");
CbProjectOther projectOther = new CbProjectOther();
projectOther.setParentId(0L);
projectOther.setProjectId(projectId);
projectOther.setCbStage(byId.getCbStage());
QueryWrapper<CbProjectOther> tWrapper = Wrappers.query(projectOther);
tWrapper.select("id","item_content as itemContent");
tWrapper.orderByAsc("id");
List<Map<String, Object>> mapList = this.listMaps(tWrapper);
return mapList;
}
@Override
public List<CbProjectOtherVo> selectDataList(CbProjectOtherBo projectOtherBo) {
List<CbProjectOtherVo> dataList = new ArrayList<>();
Assert.notNull(projectOtherBo.getProjectId(), "项目ID不能为空");
CbProjectRecord byId = cbProjectRecordService.getById(projectOtherBo.getProjectId());
Assert.notNull(byId, "项目信息不能为空");
projectOtherBo.setCbStage(byId.getCbStage());
dataList = baseMapper.selectListByProjectAndStage(projectOtherBo);
return dataList;
}
/***
*@Description: 其他费用数据解析
*@Param:
*@return: void
*@Author: Dgm
*@date: 2024/2/23 18:03
*/
@Async
public void projectOtherDataAnalysis(CbProjectBaseBo baseBo) throws Exception {
// 项目Id
Long projectId = baseBo.getProjectId();
// 成本阶段(0:标前成本 1:标后成本 2:转固成本)
Integer cbStage = baseBo.getCbStage();
Assert.notNull(projectId, "项目信息不能为空");
// 查询其他费用导入文件
List<CbProjectFile> projectFileList = projectFileService.list(Wrappers.<CbProjectFile>lambdaQuery()
.eq(CbProjectFile::getProjectId, baseBo.getProjectId())
.eq(CbProjectFile::getCbType, CbProjectConstants.CB_TYPE_OTHER_PROJECT)
.eq(CbProjectFile::getCbStage, baseBo.getCbStage())
.in(CbProjectFile::getFileParseStatus, Arrays.asList(1, 3)));
if (ObjectUtils.isEmpty(projectFileList)) {
return;
}
//文件处理
for (CbProjectFile file : projectFileList) {
if (file.getDelFlag() == 0) {
//文件下载
InputStream inputStream = ossService.downFileIO(file.getFileOssId());
if (ObjectUtil.isNull(inputStream)) {
file.setFileParseStatus(3);
file.setFailRemark("文件数据不存在");
projectFileService.updateById(file);
break;
}
//解析数据
List<CbProjectOther> importList = new ExcelUtils<>(CbProjectOther.class).importExcelAllSheet(inputStream, 1);
if (importList.isEmpty()) {
file.setFileParseStatus(3);
file.setFailRemark("表格中不存在待导入数据!");
projectFileService.updateById(file);
break;
}
// 文件名称
String name = file.getFileName();
if ("其他费".equals(name)) {
totalDataAnalysis(inputStream, name, file, projectId, cbStage);
}
name = FileNameUtil.getPrefix(name);
//解析数据
ExcelResult<CbProjectOtherImportVo> importVoExcelResult =
ExcelUtil.importExcel(inputStream, CbProjectOtherImportVo.class,new CbProjectOtherImportListener(projectId, cbStage));
log.info(importVoExcelResult.getAnalysis());
List<CbProjectOtherImportVo> importVoList = importVoExcelResult.getList();
if (CollectionUtil.isEmpty(importVoList)) {
//解析失败
log.debug(">>>>解析失败" + importVoList.size());
file.setFileParseStatus(3);
file.setFailRemark("表格中不存在待导入数据!");
projectFileService.updateById(file);
break;
}
log.debug(">>>>" + importVoList.size());
CbProjectOther rootProjectOther = new CbProjectOther();
rootProjectOther.setItemContent(name);
rootProjectOther.setParentId(0L);
rootProjectOther.setProjectId(projectId);
rootProjectOther.setCbStage(cbStage);
LambdaQueryWrapper<CbProjectOther> tWrapper = Wrappers.lambdaQuery(rootProjectOther);
CbProjectOther rootOther = this.getOne(tWrapper);
if (ObjectUtil.isEmpty(rootOther)) {
this.save(rootProjectOther);
rootProjectOther.setDealWithNumber(String.valueOf(rootProjectOther.getId()));
this.updateById(rootProjectOther);
}
Long rootMeasuresId = rootProjectOther.getId();
if (CollectionUtil.isNotEmpty(importVoList)) {
for (CbProjectOtherImportVo importVo : importVoList) {
String number = importVo.getNumber();
CbProjectOther cbProjectOther = new CbProjectOther();
//保存一级节点
if (ReUtil.isMatch(firstPattern, number) || ReUtil.isMatch(pattern3, number)) {
BeanUtil.copyProperties(importVo, cbProjectOther);
cbProjectOther.setParentId(rootMeasuresId);
} else if (ReUtil.isMatch(secondPattern, number)) {
BeanUtil.copyProperties(importVo, cbProjectOther);
// 根据no查询父级节点
CbProjectOther parentCbCostMeasure = getCbProjectOther(rootMeasuresId, number, projectId, cbStage);
String[] split = number.split("\\.");
cbProjectOther.setParentId(parentCbCostMeasure.getId());
}
String newNo = String.valueOf(rootMeasuresId).concat(".").concat(cbProjectOther.getDealWithNumber());
cbProjectOther.setDealWithNumber(newNo);
cbProjectOther.setProjectId(projectId);
cbProjectOther.setCbStage(cbStage);
this.save(cbProjectOther);
}
}
}
}
}
/***
*@Description: 解析其他费用总和
*@Param:
*@return: void
*@Author: Dgm
*@date: 2024/2/23 18:03
*/
public void totalDataAnalysis(InputStream inputStream, String name, CbProjectFile file, Long projectId, Integer cbStage) throws Exception {
//解析数据
ExcelResult<CbProjectExpenseSummaryImportVo> importVoExcelResult =
ExcelUtil.importExcel(inputStream, CbProjectExpenseSummaryImportVo.class,new CbProjectExpenseSummaryImportListener(projectId, cbStage));
log.info(importVoExcelResult.getAnalysis());
List<CbProjectExpenseSummaryImportVo> importVoList = importVoExcelResult.getList();
if (CollectionUtil.isEmpty(importVoList)) {
//解析失败
log.debug(">>>>解析失败" + importVoList.size());
file.setFileParseStatus(3);
file.setFailRemark("表格中不存在待导入数据!");
projectFileService.updateById(file);
}
log.debug(">>>>" + importVoList.size());
if (CollectionUtil.isNotEmpty(importVoList)) {
for (CbProjectExpenseSummaryImportVo importVo : importVoList) {
CbProjectExpenseSummary projectExpenseSummary = new CbProjectExpenseSummary();
BeanUtil.copyProperties(importVo, projectExpenseSummary);
projectExpenseSummary.setProjectId(projectId);
projectExpenseSummary.setCbStage(cbStage);
projectExpenseSummaryService.save(projectExpenseSummary);
}
}
}
/**
* 根据当前序号、项目id、成本阶段查询父级信息
*
* @param number
* @param projectId
* @param cbStage
* @return
*/
public CbProjectOther getCbProjectOther(Long rootMeasuresId, String number, Long projectId, Integer cbStage) {
String parentNo = number.substring(0, number.lastIndexOf('.'));
parentNo = String.valueOf(rootMeasuresId).concat(".").concat(parentNo);
CbProjectOther projectOther = new CbProjectOther();
projectOther.setDealWithNumber(parentNo);
projectOther.setProjectId(projectId);
projectOther.setCbStage(cbStage);
LambdaQueryWrapper<CbProjectOther> tWrapper = Wrappers.lambdaQuery(projectOther);
CbProjectOther other = this.getOne(tWrapper);
return other;
}
}
......@@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsk.common.core.domain.PageQuery;
import com.dsk.common.core.page.TableDataInfo;
import com.dsk.common.helper.LoginHelper;
import com.dsk.common.utils.StringUtils;
import com.dsk.component.DataAnalysisComponent;
import com.dsk.cscec.constant.CbProjectConstants;
......@@ -20,13 +21,17 @@ import com.dsk.cscec.domain.bo.*;
import com.dsk.cscec.domain.vo.CbProjectRecordSearchVo;
import com.dsk.cscec.mapper.CbProjectFileMapper;
import com.dsk.cscec.mapper.CbProjectRecordMapper;
import com.dsk.cscec.service.CbProjectExpenseSummaryService;
import com.dsk.cscec.service.CbProjectRecordService;
import com.dsk.cscec.service.CbSummaryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 项目台账表(CbProjectRecord)表服务实现类
......@@ -42,6 +47,10 @@ public class CbProjectRecordServiceImpl extends ServiceImpl<CbProjectRecordMappe
private CbProjectFileMapper projectFileMapper;
@Resource
private DataAnalysisComponent dataAnalysisComponent;
@Resource
private CbSummaryService cbSummaryService;
@Resource
private CbProjectExpenseSummaryService projectExpenseSummaryService;
/**
* 新增项目
......@@ -85,35 +94,44 @@ public class CbProjectRecordServiceImpl extends ServiceImpl<CbProjectRecordMappe
//校验项目是否存在
CbProjectRecord projectRecord = this.checkProjectExist(projectId);
List<CbProjectFile> projectFileList = new ArrayList<>();
//校验各个成本类型是否至少有1个文件
//直接费成本
this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_DIRECT_EXPENSE, CbProjectConstants.CB_TYPE_DIRECT_EXPENSE_NAME);
projectFileList.addAll(this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_DIRECT_EXPENSE, CbProjectConstants.CB_TYPE_DIRECT_EXPENSE_NAME));
//工料汇总
this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_QUANTITY_SUMMARY, CbProjectConstants.CB_TYPE_QUANTITY_SUMMARY_NAME);
projectFileList.addAll(this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_QUANTITY_SUMMARY, CbProjectConstants.CB_TYPE_QUANTITY_SUMMARY_NAME));
//措施项目
this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_MEASURE_PROJECT, CbProjectConstants.CB_TYPE_MEASURE_PROJECT_NAME);
projectFileList.addAll(this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_MEASURE_PROJECT, CbProjectConstants.CB_TYPE_MEASURE_PROJECT_NAME));
//其他项目
this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_OTHER_PROJECT, CbProjectConstants.CB_TYPE_OTHER_PROJECT_NAME);
projectFileList.addAll(this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_OTHER_PROJECT, CbProjectConstants.CB_TYPE_OTHER_PROJECT_NAME));
//现场经费
this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_SCENE_EXPENSE, CbProjectConstants.CB_TYPE_SCENE_EXPENSE_NAME);
projectFileList.addAll(this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_SCENE_EXPENSE, CbProjectConstants.CB_TYPE_SCENE_EXPENSE_NAME));
//成本汇总
this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_SUMMARY, CbProjectConstants.CB_TYPE_SUMMARY_NAME);
projectFileList.addAll(this.checkCbTypeExistFile(projectId, CbProjectConstants.CB_TYPE_SUMMARY, CbProjectConstants.CB_TYPE_SUMMARY_NAME));
//修改项目文件状态:解析中
//修改项目状态:解析中
projectRecord.setProjectFileStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
baseMapper.updateById(projectRecord);
//修改所有该项目的项目文件状态:解析中
CbProjectFileServiceImpl projectFileService = new CbProjectFileServiceImpl();
projectFileService.updateBatchById(projectFileList.stream().peek(projectFile -> projectFile.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING)).collect(Collectors.toList()));
//TODO:调各个成本类型的解析文件方法
Integer cbStage = projectRecord.getCbStage();
String username = Objects.requireNonNull(LoginHelper.getLoginUser()).getUsername();
//直接费成本
//工料汇总
CbProjectBaseBo projectBaseBo = new CbProjectBaseBo();
projectBaseBo.setProjectId(projectId);
projectBaseBo.setCbStage(projectRecord.getCbStage());
projectBaseBo.setCbStage(cbStage);
dataAnalysisComponent.quantitySummaryDataAnalysis(projectBaseBo);
//措施项目
//其他项目
//现场经费
projectExpenseSummaryService.parseSceneExpenseData(projectId,cbStage,username);
//成本汇总
cbSummaryService.importCbSummary(projectId);
}
/**
......@@ -123,13 +141,14 @@ public class CbProjectRecordServiceImpl extends ServiceImpl<CbProjectRecordMappe
* @param cbType 成本类型字典(0:直接费成本、1:工料汇总、2:措施项目、3:其他项目、4:现场经费、5:成本汇总)
* @param cbTypeName 成本类型名称
*/
private void checkCbTypeExistFile(Long projectId, Integer cbType, String cbTypeName) {
boolean isExist = projectFileMapper.exists(new LambdaQueryWrapper<CbProjectFile>()
private List<CbProjectFile> checkCbTypeExistFile(Long projectId, Integer cbType, String cbTypeName) {
List<CbProjectFile> projectFileList = projectFileMapper.selectList(new LambdaQueryWrapper<CbProjectFile>()
.eq(CbProjectFile::getProjectId, projectId)
.eq(CbProjectFile::getCbType, cbType)
//项目文件状态:解析
//项目文件状态:准备
.eq(CbProjectFile::getFileParseStatus, CbProjectConstants.PROJECT_FILE_STATUS_PREPARING));
Assert.isTrue(isExist, cbTypeName + "至少需要上传1个文件");
Assert.isFalse(projectFileList.isEmpty(), cbTypeName + "至少需要上传1个文件");
return projectFileList;
}
/**
......
......@@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsk.common.exception.ServiceException;
import com.dsk.common.helper.LoginHelper;
import com.dsk.cscec.domain.CbQuantitySummary;
import com.dsk.cscec.domain.CbQuantitySummaryActual;
import com.dsk.cscec.domain.CbSubject;
......@@ -62,7 +63,7 @@ public class CbQuantitySummaryServiceImpl extends ServiceImpl<CbQuantitySummaryM
Map<String, Object> oneMap = new HashMap<>();
List<Map<String, Object>> oneList = new ArrayList<>();
oneMap.put("name", entry.getKey());
oneMap.put("sort", cbSubjectMapper.selectOne(Wrappers.<CbSubject>lambdaQuery().eq(CbSubject::getCbSubjectName,entry.getKey())).getSort());
oneMap.put("sort", cbSubjectMapper.selectOne(Wrappers.<CbSubject>lambdaQuery().eq(CbSubject::getCbSubjectName, entry.getKey())).getSort());
for (Map.Entry<String, Map<String, List<Map<String, Object>>>> twoEntry : entry.getValue().entrySet()) {
Map<String, Object> twoMap = new HashMap<>();
List<Map<String, Object>> twoList = new ArrayList<>();
......@@ -106,11 +107,13 @@ public class CbQuantitySummaryServiceImpl extends ServiceImpl<CbQuantitySummaryM
@Transactional(rollbackFor = Exception.class)
public void updateActual(List<CbQuantitySummaryActual> list) {
if (ObjectUtils.isEmpty(list)) throw new BeanException("数据不能为空");
String nickName = LoginHelper.getLoginUser().getNickname();
for (CbQuantitySummaryActual actual : list) {
if (ObjectUtils.isEmpty(actual.getCbQuantitySummaryId())) throw new BeanException("基础数据id不能为空!");
if (ObjectUtils.isEmpty(actual.getQuantities())) throw new BeanException("工程量(本月用料)不能为空!");
if (ObjectUtils.isEmpty(actual.getRecordDate())) throw new BeanException("填写月份不能为空!");
actual.setId(ObjectUtils.isEmpty(actual.getId()) ? SecureUtil.md5(actual.getCbQuantitySummaryId() + actual.getRecordDate()) : actual.getId());
actual.setUpdateBy(nickName);
boolean b = baseActualService.saveOrUpdate(actual);
if (!b) {
log.error("CbQuantitySummaryServiceImpl.updateActual() data insert error! data:" + JSONUtil.toJsonStr(actual));
......
......@@ -28,9 +28,14 @@ import com.dsk.system.service.ISysOssService;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
......@@ -59,142 +64,183 @@ public class CbSummaryServiceImpl extends ServiceImpl<CbSummaryMapper, CbSummary
@Autowired
private ISysOssService ossService;
@Override
public void importCbProject(Long projectId) {
//获取del_flag为1的文件,若存在则根据fileId删除相关基础数据,并修改文件del_flag为2 todo
@Autowired
private TransactionTemplate transactionTemplate;
@Async
@Override
public void importCbSummary(Long projectId) {
//获取文件信息
List<CbProjectFile> cbProjectFiles = cbProjectFileMapper.selectList(new LambdaQueryWrapper<CbProjectFile>()
.eq(CbProjectFile::getProjectId, projectId)
// .eq(CbProjectFile::getCbStage, cbStage)
.eq(CbProjectFile::getCbType, CbProjectConstants.CB_TYPE_SUMMARY)
.eq(CbProjectFile::getFileParseStatus,CbProjectConstants.PROJECT_FILE_STATUS_PREPARING)
);
//获取待解析和待删除文件信息
List<CbProjectFile> cbProjectFiles = cbProjectFileMapper.selectAnalysisList(projectId, CbProjectConstants.CB_TYPE_SUMMARY, null);
//解析数据
cbProjectFiles.forEach(cbProjectFile -> {
if (cbProjectFile.getFileName().contains("项目")) {
saveCbSummaryProject(projectId,cbProjectFile);
} else if (cbProjectFile.getFileName().contains("成本科目")) {
saveCbSummaryCostAccount(projectId,cbProjectFile);
if (cbProjectFile.getDelFlag() == 1) {
//根据fileId删除相关基础数据,并删除文件
baseMapper.delete(new LambdaQueryWrapper<CbSummary>().eq(CbSummary::getCbProjectFileId, cbProjectFile.getId()));
cbProjectFileMapper.removeById(cbProjectFile.getId());
} else {
//修改文件状态
cbProjectFile.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSE_FAIL);
cbProjectFile.setFailRemark("失败原因:文件名错误");
cbProjectFileMapper.updateById(cbProjectFile);
try {
if (cbProjectFile.getFileName().contains("项目")) {
saveCbSummaryProject(projectId, cbProjectFile);
} else if (cbProjectFile.getFileName().contains("成本科目")) {
saveCbSummaryCostAccount(projectId, cbProjectFile);
} else {
throw new ServiceException("文件名错误");
}
} catch (Exception e) {
//修改文件状态
cbProjectFile.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSE_FAIL);
cbProjectFile.setFailRemark("失败原因:" + e.getMessage());
cbProjectFileMapper.updateById(cbProjectFile);
}
}
});
}
/**
* 成本汇总-项目汇总导入
*
* @param projectId
* @param file
* @return
*/
boolean saveCbSummaryProject(Long projectId, CbProjectFile file){
boolean saveCbSummaryProject(Long projectId, CbProjectFile file) {
//修改文件状态为解析中
file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
cbProjectFileMapper.updateById(file);
// file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
// cbProjectFileMapper.updateById(file);
//文件下载
InputStream inputStream = ossService.downFileIO(file.getFileOssId());
if (ObjectUtil.isNull(inputStream)) {
file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSE_FAIL);
file.setFailRemark("失败原因:文件数据不存在");
cbProjectFileMapper.updateById(file);
return false;
throw new ServiceException("文件数据不存在!");
}
//解析数据
ExcelResult<CbSummaryProjectImportVo> importVoExcelResult = ExcelUtil.importExcel(inputStream, CbSummaryProjectImportVo.class,new CbSummaryProjectImportListener(projectId,file.getId()));
ExcelResult<CbSummaryProjectImportVo> importVoExcelResult = ExcelUtil.importExcel(inputStream, CbSummaryProjectImportVo.class, new CbSummaryProjectImportListener(projectId, file.getId()));
log.info(importVoExcelResult.getAnalysis());
if (CollectionUtil.isEmpty(importVoExcelResult.getList())) {
throw new ServiceException("文件中不存在待导入数据!");
}
List<CbSummary> addList = BeanUtil.copyToList(importVoExcelResult.getList(), CbSummary.class);
this.saveBatch(addList);
//处理父级id
List<CbSummary> cbSummaryList = baseMapper.selectList(
new LambdaQueryWrapper<CbSummary>()
.eq(CbSummary::getProjectId, projectId)
.eq(CbSummary::getCbType, 1)
.orderByAsc(CbSummary::getSort)
);
for (CbSummary cbSummary:cbSummaryList) {
if(cbSummary.getLevel()==0){
continue;
transactionTemplate.execute(status -> {
try {
boolean flag = this.saveBatch(addList);
if (!flag) {
throw new ServiceException("导入数据失败");
}
//处理父级id
List<CbSummary> cbSummaryList = baseMapper.selectList(
new LambdaQueryWrapper<CbSummary>()
.eq(CbSummary::getProjectId, projectId)
.eq(CbSummary::getCbType, 1)
.orderByAsc(CbSummary::getSort)
);
for (CbSummary cbSummary : cbSummaryList) {
if (cbSummary.getLevel() == 0) {
continue;
}
//获取父级id
Integer parentLevel = cbSummary.getLevel() - 1;
CbSummary parent = cbSummaryList.stream().filter(summary -> summary.getSort() < cbSummary.getSort() && summary.getLevel() == parentLevel)
.max(Comparator.comparing(CbSummary::getSort)).get();
cbSummary.setParentId(parent.getId());
}
flag = this.updateBatchById(cbSummaryList);
if (!flag) {
throw new ServiceException("更新数据失败");
}
//修改文件状态为解析成功
file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSE_SUCCESS);
flag = cbProjectFileMapper.updateById(file) > 0;
if (!flag) {
throw new ServiceException("更新文件状态失败");
}
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
//获取父级id
Integer parentLevel = cbSummary.getLevel()-1;
CbSummary parent = cbSummaryList.stream().filter(summary -> summary.getSort()<cbSummary.getSort()&&summary.getLevel()==parentLevel)
.max(Comparator.comparing(CbSummary::getSort)).get();
cbSummary.setParentId(parent.getId());
}
this.updateBatchById(cbSummaryList);
//修改文件状态为解析成功
file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSE_SUCCESS);
cbProjectFileMapper.updateById(file);
return Boolean.TRUE;
});
return true;
}
/**
* 成本汇总-成本科目汇总导入
*
* @param projectId
* @param file
* @return
*/
boolean saveCbSummaryCostAccount(Long projectId,CbProjectFile file) {
boolean saveCbSummaryCostAccount(Long projectId, CbProjectFile file) {
//修改文件状态为解析中
file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
cbProjectFileMapper.updateById(file);
// file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSING);
// cbProjectFileMapper.updateById(file);
//文件下载
InputStream inputStream = ossService.downFileIO(file.getFileOssId());
if (ObjectUtil.isNull(inputStream)) {
file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSE_FAIL);
file.setFailRemark("失败原因:文件数据不存在");
cbProjectFileMapper.updateById(file);
return false;
throw new ServiceException("文件数据不存在");
}
//解析数据
ExcelResult<CbSummaryCostAccountImportVo> importVoExcelResult = ExcelUtil.importExcel(inputStream, CbSummaryCostAccountImportVo.class,new CbSummaryCostAccountImportListener(projectId,file.getId()));
ExcelResult<CbSummaryCostAccountImportVo> importVoExcelResult = ExcelUtil.importExcel(inputStream, CbSummaryCostAccountImportVo.class, new CbSummaryCostAccountImportListener(projectId, file.getId()));
log.info(importVoExcelResult.getAnalysis());
if (CollectionUtil.isEmpty(importVoExcelResult.getList())) {
throw new ServiceException("文件中不存在待导入数据!");
}
List<CbSummary> addList = BeanUtil.copyToList(importVoExcelResult.getList(), CbSummary.class);
this.saveBatch(addList);
//处理父级id
List<CbSummary> cbSummaryList = baseMapper.selectList(
new LambdaQueryWrapper<CbSummary>()
.eq(CbSummary::getProjectId, projectId)
.eq(CbSummary::getCbType, 1)
.orderByAsc(CbSummary::getSort)
);
for (CbSummary cbSummary:cbSummaryList) {
if(cbSummary.getLevel()==0){
continue;
transactionTemplate.execute(status -> {
try {
boolean flag = this.saveBatch(addList);
if (!flag) {
throw new ServiceException("导入数据失败");
}
//处理父级id
List<CbSummary> cbSummaryList = baseMapper.selectList(
new LambdaQueryWrapper<CbSummary>()
.eq(CbSummary::getProjectId, projectId)
.eq(CbSummary::getCbType, 2)
.orderByAsc(CbSummary::getSort)
);
for (CbSummary cbSummary : cbSummaryList) {
if (cbSummary.getLevel() == 0) {
continue;
}
//获取父级id
Integer parentLevel = cbSummary.getLevel() - 1;
CbSummary parent = cbSummaryList.stream().filter(summary -> summary.getSort() < cbSummary.getSort() && summary.getLevel() == parentLevel)
.max(Comparator.comparing(CbSummary::getSort)).get();
cbSummary.setParentId(parent.getId());
}
this.updateBatchById(cbSummaryList);
//修改文件状态为解析成功
file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSE_SUCCESS);
flag = cbProjectFileMapper.updateById(file) > 0;
if (!flag) {
throw new ServiceException("更新文件状态失败");
}
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
//获取父级id
Integer parentLevel = cbSummary.getLevel()-1;
CbSummary parent = cbSummaryList.stream().filter(summary -> summary.getSort()<cbSummary.getSort()&&summary.getLevel()==parentLevel)
.max(Comparator.comparing(CbSummary::getSort)).get();
cbSummary.setParentId(parent.getId());
}
this.updateBatchById(cbSummaryList);
//修改文件状态为解析成功
file.setFileParseStatus(CbProjectConstants.PROJECT_FILE_STATUS_PARSE_SUCCESS);
cbProjectFileMapper.updateById(file);
return Boolean.TRUE;
});
return true;
}
......@@ -255,8 +301,16 @@ public class CbSummaryServiceImpl extends ServiceImpl<CbSummaryMapper, CbSummary
list.add(cbSummaryActualListVo);
return list;
} else {
//递归列表
childrenList = getProjectSumList(bo);
// //递归列表
// childrenList = getProjectSumList(bo);
childrenList.forEach(child->{
Long count = baseMapper.selectCount(new LambdaQueryWrapper<CbSummary>().eq(CbSummary::getParentId,child.getId()));
if(count>0l){
child.setHasChildren(1);
}else {
child.setHasChildren(0);
}
});
cbSummaryActualListVo.setChildren(childrenList);
list.add(cbSummaryActualListVo);
......
<?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="com.dsk.cscec.mapper.CbProjectFileMapper">
<select id="selectAnalysisList" resultType="com.dsk.cscec.domain.CbProjectFile">
SELECT
id, project_id, cb_stage, cb_type, file_name, file_oss_id, file_oss_url, file_parse_status, fail_remark,
del_flag, create_by, create_time, update_by, update_time
FROM cb_project_file
WHERE ((del_flag = 0 and file_parse_status in (1,3)) or del_flag = 1)
and project_id=#{projectId}
<if test="cbStage != null">
and cb_stage =#{cbStage}
</if>
and cb_type = #{cbType}
</select>
<update id="removeById">
UPDATE cb_project_file SET del_flag=2 WHERE id=#{id}
</update>
</mapper>
\ No newline at end of file
<?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="com.dsk.cscec.mapper.CbProjectOtherMapper">
<select id="selectListByProjectAndStage" resultType="com.dsk.cscec.domain.vo.CbProjectOtherVo">
SELECT t.* FROM cb_project_other t WHERE t.project_id=#{projectId} AND t.cb_stage=#{cbStage} AND t.parent_id=#{parentId} ORDER BY id ASC
</select>
</mapper>
\ No newline at end of file
import request from '@/utils/request'
import request from '@/utils/request';
/**
* 获取项目详情
* @param {*} params
* @returns
*/
export const getProjectDetailApi = (params = {}) => request({
url: "",
method: "get",
params
});
//校验项目编码是否存在
export function checkProjectCodeExist (data) {
export function checkProjectCodeExist(data) {
return request({
url: '/cbProjectRecord/checkProjectCodeExist/'+data,
url: '/cbProjectRecord/checkProjectCodeExist/' + data,
method: 'get',
})
});
}
//新增项目
export function addProject (data) {
export function addProject(data) {
return request({
url: '/cbProjectRecord/addProject',
method: 'post',
data:data,
})
data: data,
});
}
//修改项目
export function editProjectInfo (data) {
export function editProjectInfo(data) {
return request({
url: '/cbProjectRecord/editProjectInfo',
method: 'PUT',
data:data,
})
data: data,
});
}
//删除项目
export function batchDeleteProject(ids) {
return request({
url: '/cbProjectRecord/batchDeleteProject/'+ids,
method: 'Delete',
});
}
//新增新阶段项目
export function addNewStageProject (data) {
export function addNewStageProject(data) {
return request({
url: '/cbProjectRecord/addNewStageProject',
method: 'POST',
data:data,
})
data: data,
});
}
//获取当前项目文件上传
export function getProjectFileUploadDetail (projectId) {
export function getProjectFileUploadDetail(projectId) {
return request({
url: '/cbProjectFile/getProjectFileUploadDetail/'+projectId,
url: '/cbProjectFile/getProjectFileUploadDetail/' + projectId,
method: 'get',
})
});
}
//获取草稿箱列表
export function getDraftDialogList (projectId) {
export function getDraftDialogList(projectId) {
return request({
url: '/cbProjectRecord/getDraftDialogList',
method: 'get',
})
});
}
//上传文件
export function uploadCbProjectFile (data) {
export function uploadCbProjectFile(data) {
return request({
url: '/cbProjectFile/uploadCbProjectFile',
method: 'post',
data
})
});
}
//删除文件
export function deleteCbProjectFile (fileId) {
export function deleteCbProjectFile(fileId) {
return request({
url: '/cbProjectFile/deleteCbProjectFile/'+fileId,
url: '/cbProjectFile/deleteCbProjectFile/' + fileId,
method: 'Delete',
})
});
}
//删除草稿
export function deleteDraft (projectId) {
export function deleteDraft(projectId) {
return request({
url: '/cbProjectRecord/deleteDraft/'+projectId,
url: '/cbProjectRecord/deleteDraft/' + projectId,
method: 'Delete',
})
});
}
//查询当前项目可删除成本阶段
export function getProjectCbStageNotDraft (relatedId) {
export function getProjectCbStageNotDraft(relatedId) {
return request({
url: '/cbProjectRecord/getProjectCbStageNotDraft/'+relatedId,
url: '/cbProjectRecord/getProjectCbStageNotDraft/' + relatedId,
method: 'get',
})
});
}
//查询当前项目可删除成本阶段
export function getProjectList(data) {
return request({
url: '/cbProjectRecord/getProjectList',
method: 'get',
params:data
});
}
//盈亏分析对比 左侧菜单
export const getProfitLossMenuTreeApi = (params = {}) => request({
url: "/cbSummary/cbNameList",
method: "get",
params
})
// 工料汇总
/**
* 获取供料汇总左侧菜单
* @param {*} params
* @returns
*/
export const getFeedSummaryMenuTreeApi = (params = {}) => request({
url: "/cb/quantity/summary/subjectTree",
method: "get",
params
})
......@@ -2,7 +2,7 @@
<div class="feed-summary-container">
<div class="feed-summary-inner">
<div class="left-side-menu">
<project-side-menu :menuTree="menuTreeList" :unique-opened="false" :default-active="defaultActive">
<project-side-menu :menuTree="menuTreeList" :menuOptions="menuOptions" :unique-opened="false" :default-active="defaultActive">
<template slot="房建类成本科目-1">
<img src="@/assets/images/projectCostLedger/icon_cost_detail_2.svg" alt="">
<div class="project-sub-menu-title-text">房建类成本科目</div>
......@@ -18,74 +18,110 @@
</template>
<script>
import ProjectSideMenu from "@/views/projectCostLedger/detail/components/ProjectSideMenu";
import { getFeedSummaryMenuTreeApi } from "@/api/projectCostLedger";
export default {
name: "feedSummary",
props: {
// 项目ID
projectId: {
type: String,
required: true,
default: ""
},
// 详情信息
projectDetailInfo: {
type: Object,
default: () => ({})
}
},
watch: {
projectDetailInfo: {
handler(newValue) {
this.comProjectDetailInfo = newValue ? newValue : {};
this.init(this.comProjectDetailInfo);
},
deep: true,
immediate: true
},
projectId: {
handler(newValue) {
this.comProjectId = newValue;
},
immediate: true
}
},
components: {
ProjectSideMenu
},
data() {
return {
menuOptions: {
nodeName: "name",
nodeValue: "name",
},
comProjectDetailInfo: {},
comProjectId: "",
defaultActive: "",
menuTreeList: [
{
nodeName: "房建类成本科目",
id: "1",
children: [
{
nodeName: "劳务分包工程",
id: "1-1",
children: [
{
nodeName: "主体工程-结构劳务",
id: "1-1-1",
children: [
{
nodeName: "结构劳务分包",
id: "1-1-1-1",
}
]
},
{
nodeName: "二次结构及粗装修劳务",
id: "1-2-1",
children: [
{
nodeName: "二次机构及粗装修劳务",
id: "1-2-1",
}
]
},
{
nodeName: "拆除、修缮、清理、改造劳...",
id: "1-3-1",
children: [
{
nodeName: "拆除、修缮、清理、改造劳...",
id: "1-3-1",
}
]
}
]
},
{
nodeName: "专业分包工程",
id: "2-1",
},
{
nodeName: "实体工程材料(土建)",
id: "3-1",
},
{
nodeName: "其他直接费成本",
id: "4-1",
},
]
},
{
nodeName: "未归类项目",
id: "2",
children: []
}
// {
// nodeName: "房建类成本科目",
// id: "1",
// children: [
// {
// nodeName: "劳务分包工程",
// id: "1-1",
// children: [
// {
// nodeName: "主体工程-结构劳务",
// id: "1-1-1",
// children: [
// {
// nodeName: "结构劳务分包",
// id: "1-1-1-1",
// }
// ]
// },
// {
// nodeName: "二次结构及粗装修劳务",
// id: "1-2-1",
// children: [
// {
// nodeName: "二次机构及粗装修劳务",
// id: "1-2-1",
// }
// ]
// },
// {
// nodeName: "拆除、修缮、清理、改造劳...",
// id: "1-3-1",
// children: [
// {
// nodeName: "拆除、修缮、清理、改造劳...",
// id: "1-3-1",
// }
// ]
// }
// ]
// },
// {
// nodeName: "专业分包工程",
// id: "2-1",
// },
// {
// nodeName: "实体工程材料(土建)",
// id: "3-1",
// },
// {
// nodeName: "其他直接费成本",
// id: "4-1",
// },
// ]
// },
// {
// nodeName: "未归类项目",
// id: "2",
// children: []
// }
]
};
},
......@@ -99,7 +135,29 @@ export default {
},
//方法集
methods: {
async init(detail = {}) {
try {
const { projectId, cbStage } = detail;
if (!projectId) return;
await this.getFeedSummaryMenuTree({
projectId,
cbStage
});
} catch (error) {
}
},
async getFeedSummaryMenuTree(params) {
try {
const result = await getFeedSummaryMenuTreeApi(params);
if (result.code == 200) {
const _tempArray = result.data;
this.menuTreeList = _tempArray;
}
} catch (error) {
}
}
},
}
</script>
......
<template>
<div class="otherProjects-container">
<div class="otherProjects-cont">
<div class="left">
<div class="left-menu">
</div>
</div>
<!--<div class="right-table">-->
<!--<div class="table-item">-->
<!--<tables-->
<!--v-if="!isSkeleton"-->
<!--:tableLoading="tableLoading"-->
<!--:tableData="tableData"-->
<!--:forData="forData1"-->
<!--:MaxPage=500-->
<!--:tableDataTotal="tableDataTotal"-->
<!--:queryParams="queryParams"-->
<!--@handle-current-change="handleCurrentChange"-->
<!--@sort-change="sortChange"-->
<!--&gt;-->
<!--<template slot="number" slot-scope="scope">-->
<!--<div>{{scope.row.number || '&#45;&#45;'}}</div>-->
<!--</template>-->
<!--<template slot="proportion" slot-scope="scope">-->
<!--<div>{{scope.row.proportion || '&#45;&#45;'}}{{scope.row.proportion ? '%':''}}</div>-->
<!--</template>-->
<!--</tables>-->
<!--</div>-->
<!--</div>-->
</div>
</div>
</template>
<script>
import Tables from "../../../../component/Tables"
import {getProfitLossMenuTreeApi} from '@/api/projectCostLedger/index'
export default {
name: "ProfitLoss",
props:{
// 项目ID
projectId: {
type: String,
required: true,
default: ""
},
// // 详情信息
// projectDetailInfo: {
// type: Object,
// default: () => ({})
// }
},
watch: {
// projectDetailInfo: {
// handler(newValue) {
// this.comProjectDetailInfo = newValue ? newValue : {};
// this.init(this.comProjectDetailInfo);
// },
// deep: true,
// immediate: true
// },
// projectId: {
// handler(newValue) {
// this.comProjectId = newValue;
// },
// immediate: true
// }
},
components: {
Tables,
},
data() {
return {
menuOptions: {
nodeName: "name",
nodeValue: "name",
},
comProjectDetailInfo: {},
comProjectId: "",
defaultActive: "",
menuTreeList: [
// {
// nodeName: "房建类成本科目",
// id: "1",
// children: [
// {
// nodeName: "劳务分包工程",
// id: "1-1",
// children: [
// {
// nodeName: "主体工程-结构劳务",
// id: "1-1-1",
// children: [
// {
// nodeName: "结构劳务分包",
// id: "1-1-1-1",
// }
// ]
// },
// {
// nodeName: "二次结构及粗装修劳务",
// id: "1-2-1",
// children: [
// {
// nodeName: "二次机构及粗装修劳务",
// id: "1-2-1",
// }
// ]
// },
// {
// nodeName: "拆除、修缮、清理、改造劳...",
// id: "1-3-1",
// children: [
// {
// nodeName: "拆除、修缮、清理、改造劳...",
// id: "1-3-1",
// }
// ]
// }
// ]
// },
// {
// nodeName: "专业分包工程",
// id: "2-1",
// },
// {
// nodeName: "实体工程材料(土建)",
// id: "3-1",
// },
// {
// nodeName: "其他直接费成本",
// id: "4-1",
// },
// ]
// },
// {
// nodeName: "未归类项目",
// id: "2",
// children: []
// }
]
}
},
//可访问data属性
created() {
console.log(this.projectId)
this.init()
},
//计算集
computed: {
},
async init(detail = {}) {
let cbStage = 1
try {
const { projectId, cbStage } = detail;
if (!projectId) return;
await this.getProfitLossMenuTree({
projectId,
cbStage
});
} catch (error) {
}
},
async getProfitLossMenuTree(params) {
try {
const result = await getProfitLossMenuTreeApi(params);
if (result.code == 200) {
const _tempArray = result.data;
this.menuTreeList = _tempArray;
}
} catch (error) {
}
},
}
</script>
<style lang="scss" scoped>
.otherProjects-container {
width: 100%;
box-sizing: border-box;
background: #ffffff;
height: 100%;
align-items: center;
.otherProjects-cont{
display: flex;
width: 100%;
height: 100%;
}
.left{
width: 220px;
height: 100%;
.left-menu{
width: 100%;
height: 100%;
border-right: 1px solid #eeeeee;
overflow: auto;
}
white-space: nowrap; /* 不换行 */
overflow: hidden; /* 超出部分隐藏 */
text-overflow: ellipsis; /* 显示省略号 */
}
.right-table{
width: calc(100% - 220px);
padding: 16px;
}
}
</style>
......@@ -85,11 +85,11 @@ export default {
//方法集
methods: {
// 事件订阅
subMenuOpen(menuPath) {
this.$emit("open", menuPath);
subMenuOpen(menuPath, menuPathArray) {
this.$emit("open", menuPath, menuPathArray);
},
subMenuClose(menuPath) {
this.$emit("close", menuPath);
subMenuClose(menuPath, menuPathArray) {
this.$emit("close", menuPath, menuPathArray);
},
menuSelect(menuPath) {
const result = this.getCurrentData(menuPath);
......@@ -120,11 +120,12 @@ export default {
// 合并默认配置
const _options = this.mergeMenuOptions(JSON.parse(JSON.stringify(this.menuOptions)));
this.tempMenuOptions = _options;
console.log(this.tempMenuOptions);
// 映射配置
const resultData = this.mapDataByMenuOptions(JSON.parse(JSON.stringify(this.comMenuTree)), _options);
if (resultData) {
this.tempMenuTree = resultData;
}
// const resultData = this.mapDataByMenuOptions(JSON.parse(JSON.stringify(this.comMenuTree)), _options);
// if (resultData) {
// this.tempMenuTree = resultData;
// }
}
},
mergeMenuOptions(options) {
......
......@@ -15,11 +15,14 @@
<direct-cost v-if="current == 'directCost'"></direct-cost>
<!-- 工料汇总 -->
<feed-summary v-if="current == 'feedSummary'"></feed-summary>
<feed-summary v-if="current == 'feedSummary'" :project-id="projectID" :project-detail-info="detailInfo"></feed-summary>
<!-- 其他项目 -->
<other-projects v-if="current == 'otherItems'"></other-projects>
<!-- 盈亏分析对比 -->
<profit-Loss v-if="current == 'profitAndLoss'" :project-id="projectID"></profit-Loss>
</div>
</div>
</div>
......@@ -35,8 +38,11 @@ import DirectCost from "@/views/projectCostLedger/detail/components/DirectCost";
import FeedSummary from "@/views/projectCostLedger/detail/components/FeedSummary";
// 其他项目
import OtherProjects from "@/views/projectCostLedger/detail/components/OtherProjects";
// 盈亏分析对比
import ProfitLoss from "@/views/projectCostLedger/detail/components/ProfitLoss";
import { v4 } from "uuid";
import { cloneDeep } from "lodash-es";
import { getProjectDetailApi } from "@/api/projectCostLedger";
export default {
name: "projectCostLedgerDetail",
components: {
......@@ -45,14 +51,18 @@ export default {
FeedSummary,
EngineeringInformation,
DirectCost,
OtherProjects
OtherProjects,
ProfitLoss
},
data() {
return {
projectID: "",
current: "",
// 详情信息变量
detailInfo: {},
detailInfo: {
projectId: "1754425038355890177",
cbStage: 0
},
toggleTabs: [
{
value: "basicEngineeringInformation",
......
......@@ -10,18 +10,18 @@
<el-form :model="formdata" label-width="82px" label-position="right" :inline="true" >
<el-row>
<el-form-item label="工程名称">
<el-input v-model="formdata.customerName" placeholder="请输入工程名称" clearable></el-input>
<el-input v-model="formdata.projectName" placeholder="请输入工程名称" clearable></el-input>
</el-form-item>
<el-form-item label="IPM项目编码" label-width="100px">
<el-input v-model="formdata.customerName" placeholder="请输入IPM项目编码" clearable></el-input>
<el-input v-model="formdata.ipmProjectNo" placeholder="请输入IPM项目编码" clearable></el-input>
</el-form-item>
<el-form-item label="成本阶段">
<el-select v-model="formdata.customerClass" placeholder="请选择" :collapse-tags="true" clearable>
<el-select v-model="formdata.cbStage" placeholder="请选择" :collapse-tags="true" clearable>
<el-option v-for="(item,index) in cbStagelist" :label="item.dictLabel" :value="item.dictValue" :key="index"></el-option>
</el-select>
</el-form-item>
<el-form-item label="项目状态">
<el-select v-model="formdata.customerClass" placeholder="请选择" :collapse-tags="true" clearable>
<el-select v-model="formdata.projectFileStatus" placeholder="请选择" :collapse-tags="true" clearable>
<el-option v-for="(item,index) in ztStagelist" :label="item.dictLabel" :value="item.dictValue" :key="index"></el-option>
</el-select>
</el-form-item>
......@@ -65,12 +65,12 @@
<template slot-scope="scope">
<div style="display:flex;align-items:center">
<!--<el-tooltip placement="top" v-if="scope.row.customerText.length>20">-->
<!--<div slot="content">{{scope.row.customerText}}</div>-->
<!--<div class="renling">-->
<!--<router-link v-if="scope.row.companyId" :to="`/enterprise/${encodeStr(scope.row.companyId)}?path=cooperationRecord&companyName=${scope.row.customerName}`" tag="a"-->
<!--class="wordprimary" v-html="scope.row.customerName"></router-link>-->
<!--<span v-else v-html="scope.row.customerName"></span>-->
<!--</div>-->
<!--<div slot="content">{{scope.row.projectName}}</div>-->
<div class="renling">
<router-link v-if="scope.row.isGetProjectDetail" :to="`/projectCostLedger/detail?projectID=${scope.row.id}`" tag="a"
class="wordprimary" v-html="scope.row.projectName"></router-link>
<span v-else v-html="scope.row.projectName"></span>
</div>
<!--</el-tooltip>-->
<!--<div class="renling" v-else>-->
<!--<router-link v-if="scope.row.companyId" :to="`/enterprise/${encodeStr(scope.row.companyId)}?path=cooperationRecord&companyName=${scope.row.customerName}`" tag="a"-->
......@@ -82,34 +82,46 @@
</template>
</el-table-column>
<el-table-column label="项目状态" prop="customerCode" width="90" :resizable="false">
<el-table-column label="项目状态" prop="customerCode" width="100" :resizable="false">
<template slot-scope="scope">
<template v-for="item in ztStagelist">
<template v-if="item.dictValue == scope.row.projectFileStatus">
<span class="zts" :class="'zt'+scope.row.projectFileStatus">{{item.dictLabel}}</span>
</template>
</template>
</template>
</el-table-column>
<el-table-column label="IPM项目编码" min-width="136">
<template slot-scope="scope">
{{scope.row.recommendOrg||"--"}}
{{scope.row.ipmProjectNo||"--"}}
</template>
</el-table-column>
<el-table-column label="文件名称" min-width="286" :resizable="false">
<template slot-scope="scope">
{{scope.row.registerRegion||"--"}}
{{scope.row.projectFileName||"--"}}
</template>
</el-table-column>
<el-table-column label="成本阶段" prop="customerCode" width="90" :resizable="false">
<template slot-scope="scope">
<template v-for="item in cbStagelist">
<template v-if="item.dictValue == scope.row.cbStage">{{item.dictLabel}}</template>
</template>
</template>
</el-table-column>
<el-table-column label="上传人" prop="customerCode" width="90" :resizable="false">
<el-table-column label="上传人" prop="updateBy" width="90" :resizable="false">
</el-table-column>
<el-table-column label="上传时间" min-width="180" :resizable="false">
<template slot-scope="scope">
{{scope.row.approveDate2||"--"}}
{{scope.row.updateTime||"--"}}
</template>
</el-table-column>
<el-table-column label="操作" min-width="256" :resizable="false" fixed="right">
<el-table-column label="操作" min-width="260" :resizable="false" fixed="right">
<template slot-scope="scope">
<span class="wordprimary tabs" @click="editpro(scope.row)">修改项目信息</span>
<span class="wordprimary tabs" @click="detailpro(scope.row)">查看导入进度</span>
<span class="worddel tabs" @click="deleetpro(scope.row)">删除</span>
<span class="worddel tabs" v-if="scope.row.projectFileStatus != 1" @click="deleetpro(scope.row)">删除</span>
</template>
</el-table-column>
</el-table>
......@@ -124,12 +136,12 @@
<el-dialog title="删除项目" :visible.sync="deletevisible" width="480px" custom-class='dialog-supplier'>
<el-divider></el-divider>
<div class="protypes">
<div class="ck" v-if="typenum>1">项目台账共有3个阶段</div>
<div class="ck" v-if="typenum>1">项目台账共有{{typenum}}个阶段</div>
<div class="ck" v-else>是否删除此项目?删除后无法返回。</div>
<div class="ck"><el-checkbox :indeterminate="indeterminate" v-model="checkAll" @change="handleCheckAllChange">删除全部</el-checkbox></div>
<div class="ck" v-if="typenum>1"><el-checkbox :indeterminate="indeterminate" v-model="checkAll" @change="handleCheckAllChange">删除全部</el-checkbox></div>
<el-checkbox-group v-model="checkds" @change="handleCheck">
<div class="ck" v-for="(item,index) in allchecks">
<el-checkbox :key="index" :label="item.label">{{item.text}}</el-checkbox>
<el-checkbox :key="index" :label="item.id">{{item.text}}</el-checkbox>
</div>
</el-checkbox-group>
</div>
......@@ -139,6 +151,7 @@
<el-button type="primary" size="small" @click="getDelete">确定删除</el-button>
</div>
</el-dialog>
<!--新增、修改弹窗-->
<el-dialog
class="pro-news"
:visible.sync="dialogVisible"
......@@ -169,7 +182,7 @@
<div class="btn btn_cancel h32" @click="dialogVisible = false">取消</div>
<div class="btn btn_primary h32" v-if="isedit && !ischeck" @click="savepro">保存</div>
<div class="btn btn_primary h32" v-if="isedit && ischeck" @click="changepro">下一步,导入数据</div>
<div class="btn btn_primary h32" v-if="!isedit && !ischeck" @click="insertPro" :class="{'btn_disabled':!queryParam.cbStage}" :disabled="!queryParam.cbStage">下一步,导入数据</div>
<div class="btn btn_primary h32" v-if="!isedit && ischeck" @click="insertPro" :class="{'btn_disabled':!queryParam.cbStage}" :disabled="!queryParam.cbStage">下一步,导入数据</div>
</div>
</el-dialog>
......@@ -233,7 +246,7 @@
checkProjectCodeExist,
deleteDraft,
editProjectInfo,
getDraftDialogList,getProjectCbStageNotDraft
getDraftDialogList,getProjectCbStageNotDraft,getProjectList,batchDeleteProject
} from '@/api/projectCostLedger/index'
import { getDicts } from '@/api/system/dict/data'
import proupload from '@/views/projectCostLedger/upload/index'
......@@ -244,10 +257,13 @@
components:{proupload,skeleton},
data() {
return {
typenum:2,
formdata:{},
typenum:0,
formdata:{
pageNum:1,
pageSize:50,
},
isSkeleton:false,
total:10,
total:0,
protitle:'',
dialogVisible:false,
cbStagelist:[],
......@@ -306,15 +322,25 @@
},
//方法集
methods: {
//获取台账列表
getlist(){
getProjectList(this.formdata).then(res=>{
if(res.code == 200){
this.total = res.total
this.formdata.pageNum = res.currentPage
this.tableData = res.rows
}else{
this.total = 0
this.tableData = []
}
})
},
handleCheckAllChange(val){
this.checkAll = val
this.checkds = []
if(val == true){
this.allchecks.forEach(item=>{
this.checkds.push(item.label)
this.checkds.push(item.id)
})
}
this.indeterminate = false
......@@ -333,8 +359,8 @@
this.ischeck = false
this.prodetail = false
this.dialogVisible = true
this.queryParam = {}
this.queryParam = [...this.queryParam,...row]
row.cbStage = row.cbStage.toString()
this.queryParam = JSON.parse(JSON.stringify(row))
this.protitle = '修改项目信息'
},
//查看进度
......@@ -347,27 +373,40 @@
deleetpro(row){
this.deletevisible = true
this.prodetail = false
getProjectCbStageNotDraft(row.relatedId).then(res=>{
let list = res.data
let cb = this.cbStagelist
let datas = []
list.forEach(item =>{
cb.for(i=>{
if(item.dictValue == i){
let arr = {'label':i,'text':item.dictLabel}
datas.push(arr)
}
console.log(row.relatedId)
if(row.hasChildren){//有多个阶段
getProjectCbStageNotDraft(row.relatedId).then(res=>{
let list = res.data
let cb = this.cbStagelist
let datas = []
cb.forEach(item=>{
list.forEach(i =>{
if(item.dictValue == i.cbStage){
let arr = {'label':i.cbStage,'text':item.dictLabel,'id':i.id}
datas.push(arr)
}
})
})
this.allchecks = datas
this.typenum = list.length
this.checkds = []
})
this.allchecks = datas
this.typenum = list.length
this.checkds = []
})
}else{
this.checkds = [row.id]
this.typenum = 1
}
},
getDelete(){
// this.checkds 勾选了要删除的数据
batchDeleteProject(this.checkds).then(res=>{
if(res.code == 200){
this.$message.success(res.msg)
this.getlist()
this.deletevisible = false
}else{
this.$message.error(res.msg)
}
})
this.getlist()
},
//返回列表
......@@ -406,17 +445,10 @@
},
clears(){
this.formdata={
customerName: '',
customerClass:[],
areas:[],
province:[],
city:[],
customerState:[],
creditLevel:[],
credential:[],
approveDateBegion:null,
approveDateEnd:null,
times:[],
projectName:'',
ipmProjectNo:'',
cbStage:'',
projectFileStatus:'',
pageSize:50,
pageNum:1,
}
......@@ -433,6 +465,7 @@
},
//修改项目
savepro(){
this.queryParam.projectId = this.queryParam.id
editProjectInfo(JSON.stringify(this.queryParam)).then(res=>{
if(res.code == 200){
this.dialogVisible = false
......@@ -442,10 +475,11 @@
},
//修改阶段
changepro(){
addNewStageProject(JSON.parse(JSON.stringify(this.queryParam))).then(res=>{
this.queryParam.projectId = this.queryParam.id
addNewStageProject(JSON.stringify(this.queryParam)).then(res=>{
this.uploadData = res.data
this.uploadData.id = this.uploadData.projectId
this.isupload = true
this.prodetail = false
})
},
//继续编辑
......@@ -738,7 +772,7 @@
padding: 0;
}
}
.wordprimary{
.wordprimary.tabs{
margin-left: 12px;
}
.worddel{
......@@ -763,4 +797,22 @@
}
}
}
.renling{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 390px;
}
.zts{
padding: 0 8px;
height: 20px;
line-height: 20px;
display: inline-block;
color: #fff;
&.zt1{
background: #FFAB44;
}
&.zt2{background: #0CBC6D}
&.zt3{background: #FF3C3C}
}
</style>
......@@ -275,6 +275,7 @@
this.formdata = JSON.parse(JSON.stringify(this.uploadData))
this.formdata.cbStage = this.formdata.cbStage.toString()
this.getDetail()
console.log(this.uploadData)
},
methods:{
goback(){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment