需求
需求分析:
1.触发时机,选择SKU的是否触发调用接口获取成本的信息,获取信息后,根据SKU和开票组织,更新对应的字段,预估成本单价。
商品报价信息中有SKU编码一栏,选择SKU编码触发标品查询操作,DomainKey为quote。且查询为系统预置,所以无法进行修改查询操作(一开始我的思路是,调用这个物料查询接口时顺便把物料详细信息查询出来,这样回显操作都不需要做)。
否定了上一种方法,选择前端改变gridModel的单元值触发afterCellValueChange函数来监听触发,然后前端根据skuid去访问后端接口,由后端请求数据中心获取物料信息,前端接收到物料信息展示到页面。
2.增加功能按钮,获取数据中台成本,用于手工获取成本,如果勾选记录只获取勾选记录成本,如果不勾选记录,就全部明细记录成功获取成本更新。
根据已选中行的数量,判断获取全部或者部分。构建请求参数,用数组保存。请求格式如下。
后端做批量查询(其实是逐条查询,因为数据中台未提供批量查询接口),后端获取数据时根据orgname过滤数据。
{
"material_code": ["69832070106000695","589320701010004484"],
"lineno": [1,2],
"orgname":["a公司","b有限公司"]
}
相关时序图,流程图如下:
问题分析:
需求1存在一个问题,要更新预估成本单价就要有开票组织,而开票组织也需要发送一个请求,这个请求不由我们控制,那我们在触发物料查询事件时和这个系统请求是并发的关系,但是我们的请求回显时要依赖系统请求返回的字段,所以要解决这个问题。
思路1:监听开票组织afterCellValueChange事件,就能保证我们的请求一定在系统请求后,但是赋值并没有使用这个函数。
思路2:做一个延时,触发监听事件后,先延时两秒,再请求后端,对性能影响大,用户体验差,
思路3:先不携带orgname做一次无开票组织查询,为什么要携带开票组织,因为可能有多条数据,然后再去获取系统请求的返回值,因为从触发到前端构造请求,到后端请求数据再返回这段时间只要网络不出现巨大波动,大概率系统请求已完成,若网络波动导致系统请求未完成则延时2秒再获取。
需求实现:
前端代码如下:
init: function (viewModel) {
function delay(ms) {
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
}
viewModel.getGridModel().on("afterCellValueChange",function (event){
let {rowIndex,cellName,value,oldValue,childrenField} =event;
if(cellName=="skuId_code"){
let param = {
material_code : [event.value.productId_code],
}
viewModel.setProxy({
ensure: {
url: "/salesQuotation/materialInfo",
method: "POST",
options: {
domainKey: "carpoly-common",
}
}
}).ensure(param, (err, result) => {
if (err) {
console.log("物料信息获取失败,原因如下:" + err.message);
return;
} else {
let dataList=result[0].data;
var cellValue = viewModel.getGridModel().getCellValue(rowIndex,"settlementOrgId_name");
if(cellValue==null){
delay(2000).then(() => {
cellValue = viewModel.getGridModel().getCellValue(rowIndex,"settlementOrgId_name");
dataList.forEach(item=>{
if(item.orgname==cellValue){
viewModel.getGridModel().setCellValue(rowIndex,"forecastCBPrice",item.nabcost_piece);
}
})
});
}
else {
dataList.forEach(item=>{
if(item.orgname==cellValue){
viewModel.getGridModel().setCellValue(rowIndex,"forecastCBPrice",item.nabcost_piece);
}
})
}
return;
}
})
}
});
viewModel.get('button118oi') && viewModel.get('button118oi').on('click', function(data) {
var gridModel = viewModel.getGridModel();
var seletData=gridModel.getSelectedRows();
let filteredData = [];
// lineno行号
// 点击获取成本单价时,如果未选中任何数据,则对所有行进行查询
if(seletData.length==0){
// 获取所有数据
let allData = gridModel.getData();
allData.forEach(item => {
if(item.hasOwnProperty('productId_code') && item.productId_code.length>0){
filteredData.push(item);
}
});
}
else{
// 对选中的行进行查询
let allData = gridModel.getSelectedRows();
allData.forEach(item => {
if(item.hasOwnProperty('productId_code') && item.productId_code.length>0){
filteredData.push(item);
}
});
}
// 将数据批量传到后端
var requestData=[];
var linenoData =[];
var orgnameData=[];
filteredData.forEach(item =>{
requestData.push(item.productId_code);
linenoData.push(item.lineno/10-1);
orgnameData.push(item.settlementOrgId_name);
});
let param = {
material_code : requestData,
lineno : linenoData,
orgname : orgnameData
}
viewModel.setProxy({
ensure: {
url: "/salesQuotation/materialInfo",
method: "POST",
options: {
domainKey: "carpoly-common",
}
}
}).ensure(param, (err, result) => {
if (err) {
console.log("物料信息获取失败,原因如下:" + err.message);
return;
} else {
result.forEach(item=>{
viewModel.getGridModel().setCellValue(item.lineNo,"forecastCBPrice",item.data.length==0?null:item.data.nabcost_piece);
})
return;
}
})
});
}
}
后端代码(展示部分):
// 存放返回结果
ArrayList<JSONObject> res = new ArrayList<>();
String TOKEN=ymsConfig.getDataFusionProductcostToken();
String uri=ymsConfig.getBipUrl()+"/iuap-data-datafusion/openapi/asset/api_productcost";
JSONObject jsonObject = new JSONObject();
// 构建请求头
HttpHeaders headers = new HttpHeaders();
headers.add("token",TOKEN);
RestTemplate restTemplate = new RestTemplate();
OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
factory.setConnectTimeout(300000);
factory.setReadTimeout(300000);
restTemplate.setRequestFactory(factory);
ArrayList<String> materialCodeList = new ArrayList<>(materialCode.get("material_code"));
// 两种处理方式:由触发时机触发的查询事件不携带orgname,不做校验
if(materialCodeList.size()==1){
jsonObject.put("material_code",materialCodeList.get(0));
HttpEntity<JSONObject> request = new HttpEntity<>(jsonObject, headers);
ResponseEntity<String> postReturne = restTemplate.postForEntity(uri, request, String.class);
JSONObject resultObject = JSONObject.parseObject(postReturne.getBody());
JSONArray dataList = (JSONArray) resultObject.get("data");
resultObject.put("data",dataList);
res.add(resultObject);
}
// 按钮触发的事件,携带orgname进行过滤
else {
// 映射对应的行号和开票组织,进行筛选和回显
ArrayList<Object> lineNos = new ArrayList<>(materialCode.get("lineno"));
ArrayList<Object> orgNames = new ArrayList<>(materialCode.get("orgname"));
for (int i = 0; i < materialCodeList.size(); i++) {
jsonObject.put("material_code",materialCodeList.get(i));
HttpEntity<JSONObject> request = new HttpEntity<>(jsonObject, headers);
ResponseEntity<String> postReturne = restTemplate.postForEntity(uri, request, String.class);
JSONObject resultObject = JSONObject.parseObject(postReturne.getBody());
resultObject.put("lineNo",lineNos.get(i));
resultObject.put("orgname",orgNames.get(i));
String filteredOrgname = orgNames.get(i).toString();
JSONArray dataList = (JSONArray) resultObject.get("data");
// 使用 Stream 过滤orgname
JSONArray filteredArray = dataList.stream()
.filter(obj -> {
return ((JSONObject) obj).get("orgname").equals(filteredOrgname);
})
.collect(Collectors.toCollection(JSONArray::new));
resultObject.put("data",filteredArray);
res.add(resultObject);
}
}
return res;