feat(project): 添加 POC 测试功能并优化项目信息相关逻辑- 在项目信息页面添加 POC 测试选项和相关记录

- 实现 POC 测试选项的动态显示和隐藏
- 添加 POC 记录的验证逻辑- 优化项目信息的查询和统计
- 调整项目高亮逻辑,使用最后一次工作更新时间
- 修复部分页面样式问题
master
chenhao 2025-06-17 11:20:24 +08:00
parent 8051d95ad4
commit 3ccb79a31d
12 changed files with 144 additions and 76 deletions

View File

@ -50,14 +50,14 @@
width:100px; width:100px;
padding:0; padding:0;
height: 30px; height: 30px;
background-color: #e74c3c; background-color: #1c84c6;
color: white; color: white;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
} }
button:hover { button:hover {
background-color: #c0392b; border-color: #1a7bb9;
} }
.topBox{ .topBox{
display: flex; display: flex;
@ -107,7 +107,7 @@
</div> </div>
<div style="font-size: 20px;text-align: left;width: 70vw;margin: 10px 0">查询结果</div> <div style="font-size: 20px;text-align: left;width: 70vw;margin: 10px 0">查询结果</div>
<div style="font-size: 16px;text-align: left;width: 70vw;font-weight: 600;"><blockquote style="border-left-color: #dd242a">产品信息</blockquote> </div> <div style="font-size: 16px;text-align: left;width: 70vw;font-weight: 600;"><blockquote style="border-left-color: #1c84c6">产品信息</blockquote> </div>
<table class="tableBOx" id="tableBOx"> <table class="tableBOx" id="tableBOx">
<thead> <thead>
<tr> <tr>
@ -123,7 +123,7 @@
</table> </table>
<div > <div >
<div style="margin: 20px 0;"> <div style="margin: 20px 0;">
<span id="tab1" class="tabBtn" onclick="changeTab(0)" style="background: #dd242a;color: #fff">相关合同</span> <span id="tab1" class="tabBtn" onclick="changeTab(0)" style="background:#1c84c6;color: #fff">相关合同</span>
<span id="tab2" class="tabBtn" onclick="changeTab(1)">标准保修</span> <span id="tab2" class="tabBtn" onclick="changeTab(1)">标准保修</span>
</div> </div>
<table class="tableBOx" id="tableBOx2"> <table class="tableBOx" id="tableBOx2">
@ -174,7 +174,7 @@
res.data.forEach((ele)=>{ res.data.forEach((ele)=>{
str+=`<tr> str+=`<tr>
<td>${ele.serialNumber}</td> <td>${ele.serialNumber}</td>
<td>${ele.model}</td> <td>${ele.productCode}</td>
<td>${ele.description}</td> <td>${ele.description}</td>
<td>${ele.productName}</td> <td>${ele.productName}</td>
<td>CN</td> <td>CN</td>
@ -222,7 +222,7 @@
} }
function changeTab(show) { function changeTab(show) {
if(!show){ if(!show){
$('#tab1').css({'background': '#dd242a','color':'#fff'}) $('#tab1').css({'background': '#1c84c6','color':'#fff'})
$('#tab2').css({'background': '#fff','color':'#333'}) $('#tab2').css({'background': '#fff','color':'#333'})
$('#tableBOx2').show() $('#tableBOx2').show()
@ -230,7 +230,7 @@
}else{ }else{
$('#tableBOx3').show() $('#tableBOx3').show()
$('#tableBOx2').hide() $('#tableBOx2').hide()
$('#tab2').css({'background': '#dd242a','color':'#fff'}) $('#tab2').css({'background': '#1c84c6','color':'#fff'})
$('#tab1').css({'background': '#fff','color':'#333'}) $('#tab1').css({'background': '#fff','color':'#333'})
} }

View File

@ -223,10 +223,9 @@
></td> ></td>
<td>POC测试</td> <td>POC测试</td>
<td> <td>
<select name="poc" class="form-control" value="0"> <select name="poc" id="poc" class="form-control" value="0" onchange="changePoc()">
<option value="">请选择</option>
<option value="1"></option>
<option value="0"></option> <option value="0"></option>
<option value="1"></option>
</select> </select>
</td> </td>
</tr> </tr>
@ -279,7 +278,7 @@
<div class="layui-tab"> <div class="layui-tab">
<ul class="layui-tab-title"> <ul class="layui-tab-title">
<li class="layui-this" lay-id="11">工作进度</li> <li class="layui-this" lay-id="11">工作进度</li>
<li lay-id="22">POC测试</li> <li lay-id="22" style="display: none" id="pocLogTab">POC测试</li>
</ul> </ul>
<div class="layui-tab-content"> <div class="layui-tab-content">
<div class="layui-tab-item layui-show"> <div class="layui-tab-item layui-show">
@ -351,8 +350,21 @@
displayInput.value = Number(rawValue).toLocaleString('en-US'); displayInput.value = Number(rawValue).toLocaleString('en-US');
} }
} }
function changePoc() {
let val = $('#poc').val();
if (val==='0'){
$('#pocLogTab').attr('style','display:none')
}else{
$('#pocLogTab').attr('style','display:inline')
}
}
function submitHandler() { function submitHandler() {
let activeTabIndex=$('.layui-tab-title .layui-this').index();
if (activeTabIndex!==1 && $('#poc').val() ==='1' && validatePoc()){
$.modal.alertWarning("请完善POC记录信息");
return ;
}
if ($.validate.form()) { if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-product-add').serialize()); $.operate.save(prefix + "/add", $('#form-product-add').serialize());
} else { } else {

View File

@ -31,87 +31,87 @@
</style> </style>
<body> <body>
<div id="config-info-component" th:fragment="pocLog()"> <div id="poc-info-component" th:fragment="pocLog()">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<input name="projectPocInfo.id" type="hidden"> <input name="projectPocInfo.id" type="hidden">
<table> <table>
<tr> <tr>
<td class="shortTd" style=" text-align: right;">服务器配置<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">服务器配置<span class="is-required">*</span></td>
<td colspan="5"><input type="text" <td colspan="5"><input type="text" required
name="projectPocInfo.serverConfig" name="projectPocInfo.serverConfig"
placeholder="服务器配置" placeholder="服务器配置"
class="form-control"></td> class="form-control"></td>
</tr> </tr>
<tr> <tr>
<td class="shortTd" style=" text-align: right;">云桌面版本<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">云桌面版本<span class="is-required">*</span></td>
<td class="inputTd"><input type="text" <td class="inputTd"><input type="text" required
name="projectPocInfo.vdiVersion" name="projectPocInfo.vdiVersion"
placeholder="云桌面版本" placeholder="云桌面版本"
class="form-control"></td> class="form-control"></td>
<td class="shortTd" style=" text-align: right;">配置终端<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">配置终端<span class="is-required">*</span></td>
<td class="inputTd"><input type="text" <td class="inputTd"><input type="text" required
name="projectPocInfo.terminalConfig" name="projectPocInfo.terminalConfig"
placeholder="配置终端" placeholder="配置终端"
class="form-control"></td> class="form-control"></td>
<td class="shortTd" style=" text-align: right;">操作系统<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">操作系统<span class="is-required">*</span></td>
<td class="inputTd"><input type="text" <td class="inputTd"><input type="text" required
name="projectPocInfo.operateSystem" name="projectPocInfo.operateSystem"
placeholder="操作系统" placeholder="操作系统"
class="form-control"></td> class="form-control"></td>
</tr> </tr>
<tr> <tr>
<td class="shortTd" style=" text-align: right;">H3C接口人<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">H3C接口人<span class="is-required">*</span></td>
<td colspan="2"><input type="text" <td colspan="2"><input type="text" required
name="projectPocInfo.h3cPerson" name="projectPocInfo.h3cPerson"
placeholder="H3C接口人" placeholder="H3C接口人"
class="form-control"></td> class="form-control"></td>
<td class="shortTd" style=" text-align: right;">H3C TEL<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">H3C TEL<span class="is-required">*</span></td>
<td colspan="2"><input type="text" name="projectPocInfo.h3cPhone" <td colspan="2"><input type="text" name="projectPocInfo.h3cPhone"
placeholder="H3C TEL" placeholder="H3C TEL" required
class="form-control"></td> class="form-control"></td>
</tr> </tr>
<tr> <tr>
<td class="shortTd" style=" text-align: right;">汇智接口人<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">汇智接口人<span class="is-required">*</span></td>
<td colspan="2"><input type="text" <td colspan="2"><input type="text" required
name="projectPocInfo.hzInterfacePerson" name="projectPocInfo.hzInterfacePerson"
placeholder="汇智接口人" placeholder="汇智接口人"
class="form-control"></td> class="form-control"></td>
<td class="shortTd" style=" text-align: right;">汇智 TEL<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">汇智 TEL<span class="is-required">*</span></td>
<td colspan="2"><input type="text" <td colspan="2"><input type="text" required
name="projectPocInfo.hzInterfacePhone" name="projectPocInfo.hzInterfacePhone"
placeholder="汇智 TEL" placeholder="汇智 TEL"
class="form-control"></td> class="form-control"></td>
</tr> </tr>
<tr> <tr>
<td class="shortTd" style=" text-align: right;">研发接口人<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">研发接口人<span class="is-required">*</span></td>
<td colspan="2"><input name="projectPocInfo.processPerson" placeholder="研发接口人" <td colspan="2"><input name="projectPocInfo.processPerson" placeholder="研发接口人" required
class="form-control" type="text"> class="form-control" type="text">
<td class="shortTd" style=" text-align: right;">研发 TEL<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">研发 TEL<span class="is-required">*</span></td>
<td colspan="2"><input name="projectPocInfo.processPhone" placeholder="研发 TEL" <td colspan="2"><input name="projectPocInfo.processPhone" placeholder="研发 TEL" required
class="form-control" type="text"></td> class="form-control" type="text"></td>
</tr> </tr>
<tr> <tr>
<td class="shortTd" style=" text-align: right;">现场接口人<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">现场接口人<span class="is-required">*</span></td>
<td colspan="2"><input name="projectPocInfo.handlePerson" placeholder="现场接口人" <td colspan="2"><input name="projectPocInfo.handlePerson" placeholder="现场接口人" required
class="form-control" type="text"> class="form-control" type="text">
<td class="shortTd" style=" text-align: right;">现场 TEL<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">现场 TEL<span class="is-required">*</span></td>
<td colspan="2"><input name="projectPocInfo.handlePhone" placeholder="现场 TEL" <td colspan="2"><input name="projectPocInfo.handlePhone" placeholder="现场 TEL" required
class="form-control" type="text"></td> class="form-control" type="text"></td>
</tr> </tr>
<tr> <tr>
<td class="shortTd" style=" text-align: right;">启动时间<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">启动时间<span class="is-required">*</span></td>
<td><input name="projectPocInfo.startDate" <td><input name="projectPocInfo.startDate" required
autocomplete="off" autocomplete="off"
class="form-control" placeholder="yyyy-MM-dd" type="text"> class="form-control" placeholder="yyyy-MM-dd" type="text">
</td> </td>
<td class="shortTd" style=" text-align: right;">预计完成时间<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">预计完成时间<span class="is-required">*</span></td>
<td><input name="projectPocInfo.planFinishTime" <td><input name="projectPocInfo.planFinishTime" required
autocomplete="off" autocomplete="off"
class="form-control" placeholder="yyyy-MM-dd" type="text"> class="form-control" placeholder="yyyy-MM-dd" type="text">
</td> </td>
<td class="shortTd" style=" text-align: right;">实际完成时间<span class="is-required">*</span></td> <td class="shortTd" style=" text-align: right;">实际完成时间<span class="is-required">*</span></td>
<td><input name="projectPocInfo.realFinishTime" <td><input name="projectPocInfo.realFinishTime" required
autocomplete="off" autocomplete="off"
class="form-control" placeholder="yyyy-MM-dd" type="text"> class="form-control" placeholder="yyyy-MM-dd" type="text">
</td> </td>
@ -137,8 +137,8 @@
<!-- 可动态添加行 --> <!-- 可动态添加行 -->
</table> </table>
</div> </div>
</div> </div>
<th:block th:include="include :: footer"/> <th:block th:include="include :: footer"/>
<th:block th:include="include :: datetimepicker-js"/> <th:block th:include="include :: datetimepicker-js"/>
@ -150,7 +150,7 @@
<tr> <tr>
<td style="text-align: center;">${length + 1}</td> <td style="text-align: center;">${length + 1}</td>
<td><input type="hidden" value="${data.id || ''}" name="projectPocInfo.projectPocInfoDetailList[${length}].id"> <td><input type="hidden" value="${data.id || ''}" name="projectPocInfo.projectPocInfoDetailList[${length}].id">
<input type="text" onclick="showDetailValue(this)" name="projectPocInfo.projectPocInfoDetailList[${length}].testProgress" class="form-control" required value="${data.testProgress || ''}"></input></td> <input type="text" required onclick="showDetailValue(this)" name="projectPocInfo.projectPocInfoDetailList[${length}].testProgress" class="form-control" required value="${data.testProgress || ''}"></input></td>
<td><input type="text" class="form-control" placeholder="保存后自动填入" value="${data.createByName || ''}" readonly></td> <td><input type="text" class="form-control" placeholder="保存后自动填入" value="${data.createByName || ''}" readonly></td>
<td><input type="text" class="form-control" placeholder="保存后自动填入" value="${data.createTime||''}" readonly></td> <td><input type="text" class="form-control" placeholder="保存后自动填入" value="${data.createTime||''}" readonly></td>
</tr>`) </tr>`)
@ -211,6 +211,19 @@
} }
}); });
function validatePoc() {
let result = false;
const pocDiv = $('#poc-info-component')
pocDiv.find('input').each(function () {
if ($(this).attr('required')) {
if (!$(this).val().trim()) {
result = true;
return false
}
}
})
return result
}
/*]]>*/ /*]]>*/

View File

@ -242,10 +242,9 @@
th:value="${#dates.format(projectInfo.estimatedOrderTime, 'yyyy-MM-dd')}"></td> th:value="${#dates.format(projectInfo.estimatedOrderTime, 'yyyy-MM-dd')}"></td>
<td>POC测试</td> <td>POC测试</td>
<td> <td>
<select name="poc" class="form-control" th:field="*{poc}" disabled> <select name="poc" id="poc" class="form-control" th:field="*{poc}" onchange="changePoc()">
<option value="">根据POC记录变化</option>
<option value="1"></option>
<option value="0"></option> <option value="0"></option>
<option value="1"></option>
</select> </select>
</td> </td>
</tr> </tr>
@ -299,7 +298,7 @@
<ul class="layui-tab-title"> <ul class="layui-tab-title">
<li class="layui-this" lay-id="11">工作进度</li> <li class="layui-this" lay-id="11">工作进度</li>
<li lay-id="33">POC记录</li> <li lay-id="33" id="pocLogTab">POC记录</li>
<li lay-id="22">操作日志</li> <li lay-id="22">操作日志</li>
</ul> </ul>
<div class="layui-tab-content"> <div class="layui-tab-content">
@ -403,7 +402,23 @@
displayInput.value = ""; displayInput.value = "";
} }
} }
function changePoc() {
let val = $('#poc').val();
console.log('----------------------------------')
console.log(val)
if (val==='0'){
$('#pocLogTab').attr('style','display:none')
}else{
$('#pocLogTab').attr('style','display:inline')
}
}
function submitHandler() { function submitHandler() {
let activeTabIndex=$('.layui-tab-title .layui-this').index();
if (activeTabIndex!==1 && $('#poc').val() ==='1' && validatePoc()){
$.modal.alertWarning("请完善POC记录信息");
return ;
}
if ($.validate.form()) { if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-product-add').serialize()); $.operate.save(prefix + "/edit", $('#form-product-add').serialize());
} else { } else {
@ -411,11 +426,17 @@
} }
} }
$(function () { $(function () {
let amount = [[${projectInfo.estimatedAmount}]] || '' let amount = [[${projectInfo.estimatedAmount}]] || ''
if (amount) { if (amount) {
document.getElementById('displayEstimatedAmount').value=amount.toLocaleString('en-US'); document.getElementById('displayEstimatedAmount').value=amount.toLocaleString('en-US');
} }
let pocVal = [[${projectInfo.poc}]];
if (pocVal==='0'){
$('#pocLogTab').attr('style','display:none')
}
initProductList() initProductList()
$("input[name='estimatedOrderTime']").datetimepicker({ $("input[name='estimatedOrderTime']").datetimepicker({
format: "yyyy-mm-dd", format: "yyyy-mm-dd",
@ -573,19 +594,7 @@
} }
function addLog(data) {
let length = $('#workLog tbody').find('tr').length
let tr = $(`
<tr>
<td style="text-align: center;">${length + 1}</td>
<td><input type="hidden" value="${data.id || ''}" name="projectWorkProgressList[${length}].id">
<input type="text" onclick="showDetailValue(this)" name="projectWorkProgressList[${length}].workContent" class="form-control" required value="${data.workContent || ''}"></input></td>
<td><input type="text" class="form-control" placeholder="保存后自动填入" value="${data.userName || ''}" readonly></td>
<td><input type="text" class="form-control" placeholder="保存后自动填入" value="${data.workTime || ''}" readonly></td>
</tr>`)
$('#workLog tbody').append(tr)
}
function showDetailValue(ele, canUpdate) { function showDetailValue(ele, canUpdate) {

View File

@ -291,7 +291,7 @@
width: 140 width: 140
}, },
{ {
field: 'updateTime', field: 'lastWorkUpdateTime',
title: '更新时间', title: '更新时间',
class: 'time3', class: 'time3',
width: 160, width: 160,
@ -380,7 +380,7 @@
function changeSort(ele, index) { function changeSort(ele, index) {
let arr = ['estimated_orderTime', 'estimated_deliverTime', 'update_time'] let arr = ['estimated_orderTime', 'estimated_deliverTime', 'last_work_update_time']
$('.sortBox').find('.timeAction').removeClass('timeAction') $('.sortBox').find('.timeAction').removeClass('timeAction')
$(ele).addClass('timeAction') $(ele).addClass('timeAction')
$('input[name="orderByColumn"]').val(arr[index]) $('input[name="orderByColumn"]').val(arr[index])
@ -397,8 +397,10 @@
$('#laydate-startTime').attr('name', 'estimatedDeliverTimeStart') $('#laydate-startTime').attr('name', 'estimatedDeliverTimeStart')
$('#laydate-endTime').attr('name', 'estimatedDeliverTimeEnd') $('#laydate-endTime').attr('name', 'estimatedDeliverTimeEnd')
} else if (timeType == 2) { } else if (timeType == 2) {
$('#laydate-startTime').attr('name', 'updateTimeStart') // $('#laydate-startTime').attr('name', 'updateTimeStart')
$('#laydate-endTime').attr('name', 'updateTimeEnd') // $('#laydate-endTime').attr('name', 'updateTimeEnd')
$('#laydate-startTime').attr('name', 'lastWorkUpdateTimeStart')
$('#laydate-endTime').attr('name', 'lastWorkUpdateTimeEnd')
} }
} }

View File

@ -108,6 +108,7 @@ public class ProjectInfo extends BaseEntity
private Date estimatedOrderTimeStart; private Date estimatedOrderTimeStart;
private Date estimatedOrderTimeEnd; private Date estimatedOrderTimeEnd;
@Excel(name = "POC测试") @Excel(name = "POC测试")
private String poc; private String poc;
private String contactEmail; private String contactEmail;
@ -158,11 +159,13 @@ public class ProjectInfo extends BaseEntity
private Date estimatedDeliverTimeEnd; private Date estimatedDeliverTimeEnd;
private Date updateTimeStart; private Date updateTimeStart;
private Date updateTimeEnd; private Date updateTimeEnd;
private Date updateTime;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd") @Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date updateTime; private Date lastWorkUpdateTime;
private Date lastWorkUpdateTimeStart;
private Date lastWorkUpdateTimeEnd;

View File

@ -210,8 +210,8 @@ public class DeliveryListServiceImpl implements IDeliveryListService {
private void updateDeliveryInfoVo(DeliveryInfoVo deliveryInfoVo, Map<Long, List<ProductInfo>> maintenanceTypeMap, List<ProductInfo> productInfos) { private void updateDeliveryInfoVo(DeliveryInfoVo deliveryInfoVo, Map<Long, List<ProductInfo>> maintenanceTypeMap, List<ProductInfo> productInfos) {
List<ProductInfo> productInfoList = maintenanceTypeMap.get(deliveryInfoVo.getOrderId()); List<ProductInfo> productInfoList = maintenanceTypeMap.get(deliveryInfoVo.getOrderId());
List<DeliveryInfoVo.ServiceInfo> serviceInfoList = new ArrayList<>(); List<DeliveryInfoVo.ServiceInfo> serviceInfoList = new ArrayList<>();
if (CollUtil.isNotEmpty(productInfoList)) {
Date startTime = deliveryInfoVo.getServiceStartTime(); Date startTime = deliveryInfoVo.getServiceStartTime();
if (CollUtil.isNotEmpty(productInfoList)) {
if (ProductInfo.ProductTypeEnum.SOFTWARE.getType().equals(deliveryInfoVo.getProductType())) { if (ProductInfo.ProductTypeEnum.SOFTWARE.getType().equals(deliveryInfoVo.getProductType())) {
for (ProductInfo productInfo : productInfoList) { for (ProductInfo productInfo : productInfoList) {
if (ProductInfo.ProductTypeEnum.SOFTWARE_MAINTENANCE.getType().equals(productInfo.getType()) && StringUtils.isNotEmpty(productInfo.getValue())) { if (ProductInfo.ProductTypeEnum.SOFTWARE_MAINTENANCE.getType().equals(productInfo.getType()) && StringUtils.isNotEmpty(productInfo.getValue())) {
@ -228,6 +228,7 @@ public class DeliveryListServiceImpl implements IDeliveryListService {
} }
} }
} }
}
if (CollUtil.isEmpty(serviceInfoList) && ProductInfo.ProductTypeEnum.HARDWARE.getType().equals(deliveryInfoVo.getProductType()) if (CollUtil.isEmpty(serviceInfoList) && ProductInfo.ProductTypeEnum.HARDWARE.getType().equals(deliveryInfoVo.getProductType())
&& CollUtil.isNotEmpty(productInfos)) { && CollUtil.isNotEmpty(productInfos)) {
@ -238,7 +239,7 @@ public class DeliveryListServiceImpl implements IDeliveryListService {
} }
deliveryInfoVo.setServiceInfo(serviceInfoList); deliveryInfoVo.setServiceInfo(serviceInfoList);
}
} }
private static Date updateStartTimeAndAddList(DeliveryInfoVo deliveryInfoVo, ProductInfo productInfo, Date startTime, List<DeliveryInfoVo.ServiceInfo> serviceInfoList) { private static Date updateStartTimeAndAddList(DeliveryInfoVo deliveryInfoVo, ProductInfo productInfo, Date startTime, List<DeliveryInfoVo.ServiceInfo> serviceInfoList) {

View File

@ -349,7 +349,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService
if (orderList.getDiscount() == null) { if (orderList.getDiscount() == null) {
throw new ServiceException("折扣不能为空"); throw new ServiceException("折扣不能为空");
} }
if (orderList.getDiscount().compareTo(BigDecimal.ONE) > 0 || orderList.getDiscount().compareTo(BigDecimal.ZERO) <= 0) { if (orderList.getDiscount().compareTo(BigDecimal.ONE) > 0 || orderList.getDiscount().compareTo(BigDecimal.ZERO) < 0) {
throw new ServiceException("折扣区间需在0-1之间"); throw new ServiceException("折扣区间需在0-1之间");
} }
if (orderList.getPrice() == null) { if (orderList.getPrice() == null) {

View File

@ -18,6 +18,8 @@ import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.dto.HomepageQueryDto;
import com.ruoyi.sip.dto.StatisticsDto;
import com.ruoyi.sip.mapper.ProjectInfoMapper; import com.ruoyi.sip.mapper.ProjectInfoMapper;
import com.ruoyi.sip.service.*; import com.ruoyi.sip.service.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -129,10 +131,16 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
Map<Long, ProjectOrderInfo> orderInfoMap = projectOrderInfos.stream().collect(Collectors.toMap(ProjectOrderInfo::getProjectId, Function.identity(), (v1, v2) -> v1)); Map<Long, ProjectOrderInfo> orderInfoMap = projectOrderInfos.stream().collect(Collectors.toMap(ProjectOrderInfo::getProjectId, Function.identity(), (v1, v2) -> v1));
LocalDate now = LocalDate.now(); LocalDate now = LocalDate.now();
for (ProjectInfo info : projectInfos) { for (ProjectInfo info : projectInfos) {
LocalDate localDate = info.getUpdateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); info.setCanGenerate(orderInfoMap.get(info.getId()) == null);
if (info.getLastWorkUpdateTime() != null) {
LocalDate localDate = info.getLastWorkUpdateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
Period between = Period.between(localDate, now); Period between = Period.between(localDate, now);
info.setHighlight(between.getMonths() >= 2); info.setHighlight(between.getMonths() >= 2);
info.setCanGenerate(orderInfoMap.get(info.getId()) == null); } else {
info.setHighlight(false);
}
} }
return projectInfos; return projectInfos;
} }
@ -153,9 +161,6 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
if (CollUtil.isNotEmpty(projectInfo.getCompetitorList())) { if (CollUtil.isNotEmpty(projectInfo.getCompetitorList())) {
projectInfo.setCompetitor(projectInfo.getCompetitorList().stream().filter(StringUtils::isNotEmpty).collect(Collectors.joining(","))); projectInfo.setCompetitor(projectInfo.getCompetitorList().stream().filter(StringUtils::isNotEmpty).collect(Collectors.joining(",")));
} }
if (projectInfo.getProjectPocInfo()!=null && CollUtil.isNotEmpty(projectInfo.getProjectPocInfo().getProjectPocInfoDetailList())){
projectInfo.setPoc("1");
}
int i = projectInfoMapper.insertProjectInfo(projectInfo); int i = projectInfoMapper.insertProjectInfo(projectInfo);
saveOtherInfo(projectInfo); saveOtherInfo(projectInfo);
return i; return i;
@ -229,18 +234,9 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
//如果没有 变更编码 是否考虑高并发加锁 //如果没有 变更编码 是否考虑高并发加锁
setProjectCode(projectInfo); setProjectCode(projectInfo);
} }
int newWorkSize = projectInfo.getProjectWorkProgressList() == null ? 0 : projectInfo.getProjectWorkProgressList().size();
int existWorkSize = oldProjectInfo.getProjectWorkProgressList() == null ? 0 : oldProjectInfo.getProjectWorkProgressList().size();
boolean changeWork = newWorkSize > existWorkSize;
// 更新项目信息 // 更新项目信息
if (changeWork) {
projectInfo.setUpdateTime(DateUtils.getNowDate()); projectInfo.setUpdateTime(DateUtils.getNowDate());
} projectInfo.setUpdateBy(ShiroUtils.getUserId().toString());
if (projectInfo.getProjectPocInfo()!=null && CollUtil.isNotEmpty(projectInfo.getProjectPocInfo().getProjectPocInfoDetailList())){
projectInfo.setPoc("1");
}
int result = projectInfoMapper.updateProjectInfo(projectInfo); int result = projectInfoMapper.updateProjectInfo(projectInfo);
//变更其它信息 //变更其它信息
saveOtherInfo(projectInfo); saveOtherInfo(projectInfo);
@ -284,6 +280,7 @@ public class ProjectInfoServiceImpl implements IProjectInfoService {
formatterDate(projectInfo.getEstimatedOrderTime())); formatterDate(projectInfo.getEstimatedOrderTime()));
// logIndex = compareField(logContent, logIndex, "预计发货时间", formatterDate(oldProjectInfo.getEstimatedDeliverTime()), formatterDate(projectInfo.getEstimatedDeliverTime())); // logIndex = compareField(logContent, logIndex, "预计发货时间", formatterDate(oldProjectInfo.getEstimatedDeliverTime()), formatterDate(projectInfo.getEstimatedDeliverTime()));
logIndex = compareField(logContent, logIndex, "竞争对手", oldProjectInfo.getCompetitor(), projectInfo.getCompetitor()); logIndex = compareField(logContent, logIndex, "竞争对手", oldProjectInfo.getCompetitor(), projectInfo.getCompetitor());
logIndex = compareField(logContent, logIndex, "poc记录", oldProjectInfo.getPoc(), projectInfo.getPoc());
logIndex = compareField(logContent, logIndex, "关键技术问题", oldProjectInfo.getKeyProblem(), projectInfo.getKeyProblem()); logIndex = compareField(logContent, logIndex, "关键技术问题", oldProjectInfo.getKeyProblem(), projectInfo.getKeyProblem());
logIndex = compareField(logContent, logIndex, "项目简述", oldProjectInfo.getProjectDesc(), projectInfo.getProjectDesc()); logIndex = compareField(logContent, logIndex, "项目简述", oldProjectInfo.getProjectDesc(), projectInfo.getProjectDesc());
if (logIndex > 1) { if (logIndex > 1) {

View File

@ -327,7 +327,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService {
Sheet sheet = writeSheetHolder.getSheet(); Sheet sheet = writeSheetHolder.getSheet();
// 基础列范围(前 25 列) // 基础列范围(前 25 列)
if (columnIndex >= 0 && columnIndex <= 25) { if (columnIndex >= 0 && columnIndex <= 26) {
// 自适应列宽逻辑 // 自适应列宽逻辑
sheet.setColumnWidth(columnIndex, 256 * 30); // 设置固定宽度为 20 个字符 sheet.setColumnWidth(columnIndex, 256 * 30); // 设置固定宽度为 20 个字符
} }

View File

@ -1,5 +1,7 @@
package com.ruoyi.sip.service.impl; package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -117,7 +119,18 @@ public class ProjectProductInfoServiceImpl implements IProjectProductInfoService
if (stringJoiner.length() > 0) { if (stringJoiner.length() > 0) {
throw new ServiceException(StringUtils.format("产品编码[{}]在产品库中未找到,请确认后重试", stringJoiner.toString())); throw new ServiceException(StringUtils.format("产品编码[{}]在产品库中未找到,请确认后重试", stringJoiner.toString()));
} }
for (ProjectProductInfo info : list) {
//计算价格 防止前端价格计算错误
if (info.getGuidanceDiscount() != null && info.getDiscount() == null) {
info.setDiscount(info.getGuidanceDiscount());
}
if (info.getCataloguePrice() != null && info.getDiscount() != null) {
info.setPrice(info.getCataloguePrice().multiply(info.getDiscount()).setScale(2, RoundingMode.HALF_UP));
}
if (info.getPrice() != null && info.getQuantity() != null) {
info.setAllPrice(info.getPrice().multiply(new BigDecimal(info.getQuantity())).setScale(2, RoundingMode.HALF_UP));
}
}
List<ProjectProductInfo> projectProductInfos = projectProductInfoMapper.selectProjectProductInfoListByProjectId(Collections.singletonList(list.get(0).getProjectId())); List<ProjectProductInfo> projectProductInfos = projectProductInfoMapper.selectProjectProductInfoListByProjectId(Collections.singletonList(list.get(0).getProjectId()));
Set<Long> idSet = list.stream().map(ProjectProductInfo::getId).collect(Collectors.toSet()); Set<Long> idSet = list.stream().map(ProjectProductInfo::getId).collect(Collectors.toSet());

View File

@ -70,10 +70,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
t1.update_time, t1.update_time,
t1.customer_user_name,t1.customer_phone,t1.partner_email,t1.partner_user_name,t1.h3c_person,t1.poc,t1.h3c_phone, t1.customer_user_name,t1.customer_phone,t1.partner_email,t1.partner_user_name,t1.h3c_person,t1.poc,t1.h3c_phone,
t2.agent_name,t2.contact_email,t2.contact_phone,t2.contact_person, t2.agent_name,t2.contact_email,t2.contact_phone,t2.contact_person,
t3.user_name as hz_support_user_name t3.user_name as hz_support_user_name,
t4.work_time as last_work_update_time
from project_info t1 from project_info t1
left join agent_info t2 on t1.agent_code = t2.agent_code left join agent_info t2 on t1.agent_code = t2.agent_code
left join sys_user t3 on t1.hz_support_user=t3.user_id left join sys_user t3 on t1.hz_support_user=t3.user_id
left join (select max(work_time) work_time,project_id from project_work_progress group by project_id) t4 ON t1.id=t4.project_id
</sql> </sql>
<select id="selectProjectInfoList" parameterType="ProjectInfo" resultMap="ProjectInfoResult"> <select id="selectProjectInfoList" parameterType="ProjectInfo" resultMap="ProjectInfoResult">
@ -144,6 +147,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</choose> </choose>
</if>
<if test="lastWorkUpdateTimeStart != null or lastWorkUpdateTimeEnd != null">
<choose>
<when test="lastWorkUpdateTimeStart != null and lastWorkUpdateTimeEnd != null">
and t4.work_time between date_format(#{lastWorkUpdateTimeStart}, '%Y-%m-%d 00:00:00') and date_format(#{lastWorkUpdateTimeEnd}, '%Y-%m-%d 23:59:59')
</when>
<when test="lastWorkUpdateTimeStart != null">
and t4.work_time <![CDATA[ >= ]]> date_format(#{lastWorkUpdateTimeStart}, '%Y-%m-%d 00:00:00')
</when>
<when test="lastWorkUpdateTimeEnd != null">
and t4.work_time <![CDATA[ <= ]]> date_format(#{lastWorkUpdateTimeEnd}, '%Y-%m-%d 23:59:59')
</when>
</choose>
</if> </if>
<if test="competitor != null and competitor != ''"> and t1.competitor = #{competitor}</if> <if test="competitor != null and competitor != ''"> and t1.competitor = #{competitor}</if>
<if test="countryProduct != null and countryProduct != ''"> and t1.country_product = #{countryProduct}</if> <if test="countryProduct != null and countryProduct != ''"> and t1.country_product = #{countryProduct}</if>