unit json_dypSave; interface uses REST.Client, REST.Types, System.JSON, Winapi.ActiveX, FMX.Forms ,system.NetEncoding, system.SysUtils, System.Classes, uKsoap , uSafeLog, uWorkOrderRecordUnit; type TDevRecord=record //单表内容 ///mirror-plate/put/product/ P_ORG_CODE:string; P_LOT:string; P_BC:string; P_PC:string; P_LINE:string; P_LINE_NUM:string; P_LOT_TYPE:string; P_TROLLEY_NUM:string; P_COPPER_MODEL:string; P_BUFFER_TYPE:string; P_ID:string; P_CREATION_DATE:string; vParentId:Integer; vId:Integer; end; TKJSonSave = class private FP_ORG_CODE:string; //厂区 FP_WORK_NUM:string; //工号 FP_PC:string; //工艺 FP_LINE:string; //线别 FP_LINE_NUM:string; //线别编号 FP_Lot:string; //单号 FP_Goods_Num:string; //二维码 FP_Lot_Num:Integer; //单号数量 FP_Traceability_ID:double; //主表ID FThreadId:Integer; FFixture_Code:string; // FP_Token:string; FOnLine:boolean; public FList_pro_process, List_system_users, List_pro_workorder, List_Code_workorder: TStrings; list_md_workstation, list_pro_task, list_pro_Temp, List_pro_workorderEntry: TStrings; // 工作站,生产任务表 function REST_Value(Value: String; sKey: String): String; function REST_pro_List(const Value: String; const iValue: Integer; var sError:string):String; function Thread_xxcc_work_num_f(vP_ORG_CODE,vP_WORK_NUM,vP_PC,vP_LINE:string;var sError:string):boolean; function xxcc_work_num_f(vP_ORG_CODE,vP_WORK_NUM,vP_PC,vP_LINE:string;var sError:string):boolean; function Insert_CM_WIP_PROCESS_LINE_HISTORY_NEW(vLotNoRecord:TLotNoRecord;var sError:string):boolean; function Thread_Insert_CM_WIP_PROCESS_LINE_HISTORY_NEW(vLotNoRecord:TLotNoRecord;var sError:string):boolean; procedure ClearData(); //清除 廠區 工號 製程 線別 信息 constructor Create; virtual; destructor Destroy; override; end; function KJSon():TKJSonSave; var FKJSon:TKJSonSave; // sbaseUrl:String; implementation uses uProReportUnit, json_webservice; //http://iot.mrpiot.com:8924 function KJSon():TKJSonSave; begin if FKJSon = nil then FKJSon := TKJSonSave.Create; Result := FKJSon; end; constructor TKJSonSave. Create; begin inherited; ClearData(); end; destructor TKJSonSave. Destroy; begin FList_pro_process.Free; List_system_users.Free; List_pro_workorder.Free; List_Code_workorder.Free; list_md_workstation.Free; List_pro_workorderEntry.Free; list_pro_task.Free; list_pro_temp.Free; // FKJSon.Destroy; inherited Destroy; end; procedure TKJSonSave. ClearData(); //清除 廠區 工號 製程 線別 信息 begin FList_pro_process:= TStringList.Create; List_system_users:= TStringList.Create; List_pro_workorder:= TStringList.Create; List_pro_workorderEntry:= TStringList.Create; List_Code_workorder:= TStringList.Create; list_md_workstation:= TStringList.Create; list_pro_task:= TStringList.Create; list_pro_temp:= TStringList.Create; // P_ORG_CODE:=''; // P_WORK_NUM:=''; // P_PC:=''; // P_LINE:=''; // FP_LINE_NUM:=''; end; function TKJSonSave. REST_Value(Value: String; sKey: String): String; var // JsonString: string; //processName JsonObject: TJsonObject; begin Result := ''; JsonObject := TJsonObject.ParseJSONValue(Value) as TJsonObject; if (JsonObject <> nil) and (JsonObject.Values[sKey]<>nil) then begin Result := StringReplace(JsonObject.Values[sKey].ToString, '"', '', [rfReplaceAll]); end; end; function TKJSonSave. REST_pro_List(const Value: String; const iValue: Integer; var sError:string):String; begin case iValue of 0: WebJSon.query_user_profile('/prod-api/mes/md/panhao/list?number=&pageNum=1&pageSize=30', iValue, nil, sError); 1: begin //通过工单查工序 // FList_pro_process.Clear; // list_pro_Temp.Clear; if List_pro_workorder.Count=0 then exit; WebJSon.query_user_profile('/prod-api/masterdata/material/'+ REST_Value(List_pro_workorder.Strings[0],'materialId'), iValue, list_pro_Temp, sError); if list_pro_Temp.Count=0 then exit; WebJSon.query_user_profile('/prod-api/production/route/'+ REST_Value(list_pro_Temp.Strings[0],'routeId'), iValue, FList_pro_process, sError); // http://192.168.5.9/prod-api/production/route/11 end; 2: begin //查用户 WebJSon.query_user_profile(Format('/prod-api/system/user/list?userName=%s&pageSize=30&pageNum=1', [Value]), iValue, List_system_users, sError); end; 3: begin //查工单 WebJSon.query_user_profile(Format('/prod-api/production/workOrder/list?pageNum=1&pageSize=30&proStatus=B&number=%s', [Value]), iValue, List_pro_workorder, sError); end; 4: begin //查二维码 WebJSon.query_user_profile(Format('/prod-api/production/report/list?pageNum=1&pageSize=30%s', [Value]), iValue, List_Code_workorder, sError); end; 5: begin //查二维码 WebJSon.query_user_profile(Format('/prod-api/production/workOrder/list?pageNum=1&pageSize=30&proStatus=B%s', [Value]), iValue, list_md_workstation, sError); end; 6: begin //查报工单 //findTaskByOrderCode WebJSon.query_user_profile(Format('/prod-api/production/report/list?%s', [Value]), iValue, list_pro_task, sError); end; 7: begin //ID查二维码 //findTaskByOrderCode WebJSon.query_user_profile(Format('/prod-api/production/report/list?%s', [Value]), iValue, list_pro_Temp, sError); end; 8: begin //查子工单 WebJSon.query_user_profile(Format('/prod-api/production/workOrder/getInfoByEntryId/%s', [Value]), iValue, List_pro_workorderEntry, sError); end; 9: begin //查所有工序 WebJSon.query_user_profile('/prod-api/production/process/list?processCode=&processName=&enableFlag=&pageNum=1&pageSize=100', iValue,FList_pro_process, sError); end; end; end; function TKJSonSave. xxcc_work_num_f(vP_ORG_CODE,vP_WORK_NUM,vP_PC,vP_LINE:string;var sError:string):boolean; //var // a:compeq_webservice.xxcc_work_num_f; // Response:xxcc_work_num_fResponse; begin WorkLog.MessageInfo('提交数据main:' + sError); if not FOnLine then begin Result:=true;Exit; end; sError:= Format('%s,%s,%s,%s',[vP_ORG_CODE,vP_WORK_NUM,vP_PC,vP_LINE]); WorkLog.MessageInfo('提交数据:' + sError); Result:=false; // a:=compeq_webservice.xxcc_work_num_f.create; try // a.P_ORG_CODE:=vP_ORG_CODE; // a.P_WORK_NUM:=vP_WORK_NUM; // a.P_PC:=vP_PC; // a.P_LINE:=vP_LINE; // DbApiLog.MessageInfo('xxcc_work_num_f 请求:P_ORG_CODE=%s,P_WORK_NUM=%s,P_PC=%s,P_LINE=%s',[vP_ORG_CODE,vP_WORK_NUM,vP_PC,vP_LINE]); // try // Response:=compeq_webservice.GetServiceSoap().xxcc_work_num_f(a); //System.False,'',FRIO // Result:=Response.xxcc_work_num_fResult.ToUpper='OK'; // DbApiLog.MessageInfo('xxcc_work_num_f 返回:%s',[Response.xxcc_work_num_fResult]); // if Result then // begin // FP_ORG_CODE:=vP_ORG_CODE; // FP_WORK_NUM:=vP_WORK_NUM; // FP_PC:=vP_PC; // FP_LINE:=vP_LINE; // end // else //返回出错信息 // begin // sError:= Response.xxcc_work_num_fResult; // end; // except // on e:Exception do // begin // Result:=false; // DbApiLog.Error('xxcc_work_num_f 错误:%s',[ChangeErrorInfo(E.Message)]); // sError:=ChangeErrorInfo(E.Message); // end; // end; finally // a.Free; end; end; function TKJSonSave. Thread_xxcc_work_num_f(vP_ORG_CODE,vP_WORK_NUM,vP_PC,vP_LINE:string;var sError:string):boolean; var ssError:string; bThreadResult:boolean; begin Result:=false; bThreadResult:=false; FThreadId:=0; TThread.CreateAnonymousThread( procedure var bResult:boolean; begin CoInitialize(nil); try bResult:=xxcc_work_num_f(vP_ORG_CODE,vP_WORK_NUM,vP_PC,vP_LINE,ssError); TThread.Synchronize(nil, procedure begin bThreadResult:=bResult; FThreadId:=1; end); finally CoUninitialize; end; end).Start; while FThreadId=0 do Application.ProcessMessages; Result:=bThreadResult; sError:=ssError; end; function LocateJSONRow(List: TStrings; Conditions: TJSONObject): Integer; var I: Integer; JSONRow, Value: TJSONValue; DataObj: TJSONObject; ConditionPair: TJSONPair; Key, DataStr, ConditionStr: string; IsMatch: Boolean; begin Result := -1; // 默认未找到 // 添加调试日志 WorkLog.MessageInfo('开始定位,条件数量: %d', [Conditions.Count]); for I := 0 to List.Count - 1 do begin try // 解析 JSON JSONRow := TJSONObject.ParseJSONValue(List[I]); if not Assigned(JSONRow) then begin // WorkLog.MessageInfo('行 %d: JSON 解析失败', [I]); Continue; end; // 检查是否为对象 if not (JSONRow is TJSONObject) then begin // WorkLog.MessageInfo('行 %d: 不是 JSON 对象', [I]); JSONRow.Free; Continue; end; DataObj := TJSONObject(JSONRow); IsMatch := True; // 调试:输出当前行关键信息 if DataObj.TryGetValue('workorderCode', Value) then WorkLog.MessageInfo('检查行 %d: workorderCode=%s', [I, Value.Value]) else WorkLog.MessageInfo('检查行 %d: workorderCode 不存在', [I]); // 检查所有条件 for ConditionPair in Conditions do begin Key := ConditionPair.JsonString.Value; // 调试日志 // WorkLog.MessageInfo('-- 检查条件: %s=%s', [Key, ConditionPair.JsonValue.Value]); // 获取数据值 if not DataObj.TryGetValue(Key, Value) then begin // WorkLog.MessageInfo('-- 行 %d: 缺少键 %s', [I, Key]); IsMatch := False; Break; end; // 处理 null 值 if (Value is TJSONNull) then begin if not (ConditionPair.JsonValue is TJSONNull) then begin // WorkLog.MessageInfo('-- 行 %d: %s 为 null', [I, Key]); IsMatch := False; Break; end; Continue; end; // 转换为字符串并修剪空格 DataStr := Trim(Value.Value); ConditionStr := Trim(ConditionPair.JsonValue.Value); // 比较值(不区分大小写) if not SameText(DataStr, ConditionStr) then begin WorkLog.MessageInfo('-- 行 %d: %s 不匹配 (%s ≠ %s)', [I, Key, DataStr, ConditionStr]); IsMatch := False; Break; end; end; // 找到匹配行 if IsMatch then begin Result := I; WorkLog.MessageInfo('找到匹配行: %d', [I]); // JSONRow.Free; Exit; end; finally if Assigned(JSONRow) then JSONRow.Free; end; end; WorkLog.MessageInfo('未找到匹配行'); end; function TKJSonSave. Insert_CM_WIP_PROCESS_LINE_HISTORY_NEW(vLotNoRecord:TLotNoRecord;var sError:string):boolean; var Params: TStringList; sProWork, sProWorkEntry: String; // sTemp: string; Conditions: TJSONObject; RowIndex: Integer; prm: TProReportMapper; begin Result:=false; // if list_md_workstation.Count=0 then // begin // REST_pro_List('', 5, sError); // end; //查询报工单 // if list_pro_task.Count=0 then begin // REST_pro_List('&processCode='+fDevRecord.P_LINE, 6, sError); REST_pro_List('pageNum=1&pageSize=30&workOrderNumber=' + fDevRecord.P_LOT + '&snCode=' + fDevRecord.P_ORG_CODE, 6, sError); //取报工单 end; WorkLog.MessageInfo('提交数据12:%s,%d,%d', [sError, FList_pro_process.Count,fDevRecord.P_LINE_index]);// FList_pro_process.IndexOf(fDevRecord.P_LINE)]); // if list_md_workstation.Count=0 then exit; if (list_pro_task.Count=0) and (fDevRecord.P_LINE_index>0) then begin sError:= Format('产品还没有在第一站生产%s',['']); exit; // and (fDevRecord.P_LINE<>'PROCESS557') end; WorkLog.MessageInfo('提交数据12-1:%s,%s',['number:' + fDevRecord.P_LOT,'processCode:' + IntToStr(fDevRecord.P_LINE_id)]); if (list_pro_task.Count>0) then begin RowIndex:= -1; // 创建查询条件 Conditions := TJSONObject.Create; try // Conditions.AddPair('number', fDevRecord.P_LOT); if fDevRecord.P_LINE_index-1>-1 then begin sTemp:= REST_Value(KJson.FList_pro_process.Strings[fDevRecord.P_LINE_index-1],'id'); Conditions.AddPair('stationId', sTemp); // Conditions.AddPair('status', TJSONNumber.Create(0)); // 执行查询 // RowIndex := LocateJSONRow(list_pro_task, Conditions); RowIndex:= list_pro_task[0].IndexOf('"stationId":' + sTemp); //从最上面的数据取工号卡关 WorkLog.MessageInfo('提交数据13: %d, %s, %s',[RowIndex, sTemp, list_pro_task[0]]); end; finally Conditions.Free; end; if (RowIndex<0) and (fDevRecord.P_LINE_index=0) and (vLotNoRecord.P_OFF_NET=-1) then //判断是不是第一个工序,去掉维修的 begin sTemp:= REST_Value(KJson.FList_pro_process.Strings[0],'id'); //工序列表 RowIndex:= list_pro_task[0].IndexOf('"stationId":' + sTemp); WorkLog.MessageInfo('提交数据14: %d, %s, %s',[RowIndex, sTemp, list_pro_task[0]]); sError:= '没有报工数据'; end; if (RowIndex<0) and (vLotNoRecord.P_OFF_NET=-1) then begin if list_pro_task.Count>0 then begin WorkLog.MessageInfo('数据列表14:%S',[list_pro_task.Text]); sError:= Format('产品当前刚过站:%s',[REST_Value(list_pro_task.Strings[0], 'stationName')]); end; exit; end; // // if RowIndex>-1 then // begin // sTemp:= list_pro_task.Strings[RowIndex]; // end // else // begin // // end; end; //检查工单有没有数据 if (List_pro_workorder.Count=0) then begin WorkLog.MessageInfo('工单数据:%d',[List_pro_workorder.Count]); sError:= '没有工单数据'; Exit; end; sProWork:= List_pro_workorder.Strings[0]; //取工单数据 WorkLog.MessageInfo('提交数据15: %d,RowIndex:%d',[List_pro_workorderEntry.Count,RowIndex]); REST_pro_List(''+ REST_Value(sProWork,'id'), 8, sError); if List_pro_workorderEntry.Count>0 then begin sProWorkEntry:= List_pro_workorderEntry.Strings[0]; //取子工单数据 fPro_feedback.work_order_entry_id:= StrToInt(REST_Value(sProWorkEntry,'id')); end; prm:= TProReportMapper.Create; Params:= TStringList.Create; try fPro_feedback.material_number:= REST_Value(sProWork,'materialNumber'); // fPro_feedback.quality_status:= vLotNoRecord.P_DIE_NAME; // fPro_feedback.workstationname:= REST_Value(sTemp,'workstationName'); // // fPro_feedback.workorderId:= StrToInt(REST_Value(sTemp,'id')); // fPro_feedback.workorderCode:= REST_Value(sTemp,'workorderCode'); // fPro_feedback.workorderName:= REST_Value(sTemp,'workorderName'); // // fPro_feedback.taskId:= StrToInt(REST_Value(sTemp,'id')); // fPro_feedback.taskCode:= REST_Value(sTemp,'taskCode'); // // fPro_feedback.itemId:= StrToInt(REST_Value(sTemp,'itemId')); // 物料ID(整数) // fPro_feedback.itemCode:= (REST_Value(sTemp,'itemCode')); // 物料编码(字符串) // fPro_feedback.itemName:= (REST_Value(sTemp,'itemName')); // 物料名称(字符串) // fPro_feedback.unitOfMeasure:= (REST_Value(sTemp,'unitOfMeasure')); // 计量单位(字符串) // // WorkLog.MessageInfo('提交数据2:' + sTemp); fPro_feedback.station_id:= fDevRecord.P_Line_id; fPro_feedback.station_name:= fDevRecord.P_Line_name; fPro_feedback.work_order_number:= fDevRecord.P_LOT; //工单号 fPro_feedback.sn_array:= fDevRecord.P_ORG_CODE; //产品二维码 if fDevRecord.P_ORG_CODE_id<>'' then fPro_feedback.material_no:= fDevRecord.P_ORG_CODE_id; //产品二维码id // fPro_feedback.material_no:= fDevRecord.P_LOT; //dyp产品ID WorkLog.MessageInfo('提交数据16: %d',[List_system_users.Count]); // 人员信息参数 if KJSon.List_system_users.Count>0 then fPro_feedback.report_user_id:= StrToInt(REST_Value(KJSon.List_system_users[0],'userId')); // 报工人ID - 必须字段 fPro_feedback.report_user_name:= fDevRecord.P_BC; // 操作人姓名(字符串) fPro_feedback.create_by:= fDevRecord.P_BC; // 创建人(字符串) fPro_feedback.update_by:= fDevRecord.P_BC; // 更新人(字符串) // // // 时间戳参数 fPro_feedback.create_time:= Now(); // 创建时间(日期时间字符串) fPro_feedback.report_time:= Now(); // 报工时间(日期时间字符串) fPro_feedback.update_time:= Now(); // 更新时间(日期时间字符串) // fPro_feedback.finishedTime:= FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()); // 完成时间(日期时间字符串) fPro_feedback.report_quantity:= 1; // 实际完成数量(浮点数) fPro_feedback.qualified_quantity:= 1; // 订单需求数量(浮点数) // fPro_feedback.workOrderQuentity:= StrToFloat(REST_Value(sTemp,'quantity')); // 工单计划数量(浮点数) // fPro_feedback.reportingProgress:= (fPro_feedback.quantity/fPro_feedback.orderQuantity) * 100; // 进度百分比(浮点数) if vLotNoRecord.P_DIE_NAME='-1' then vLotNoRecord.P_DIE_NAME:= '合格'; fPro_feedback.quality_status:= vLotNoRecord.P_DIE_NAME; //是否合格 fPro_feedback.ord_Temp1:= vLotNoRecord.P_DIE_USE_NUM; //温度 fPro_feedback.ord_Temp2:= vLotNoRecord.P_LINE_SPEED; //距离 fPro_feedback.ord_Temp3:= vLotNoRecord.P_ELE_CUR_DENSITY; //回波时间 fPro_feedback.ord_Temp4:= vLotNoRecord.P_ELE_AREA1; //幅值 fPro_feedback.ord_Temp5:= vLotNoRecord.P_PRODUCT_PRESSURE; //入水盲区 fPro_feedback.ord_Temp6:= vLotNoRecord.P_COM_TEMPERATURE; //底噪 if vLotNoRecord.P_SIDE<>'' then fPro_feedback.ord_Temp7:= StrToFloat(vLotNoRecord.P_SIDE); //出水盲区 if vLotNoRecord.P_SHORT_CIRCUIT<>'' then fPro_feedback.ord_Temp8:= StrToFloat(vLotNoRecord.P_SHORT_CIRCUIT); //盲区差值 if vLotNoRecord.P_SHORT_CIRCUIT<>'' then fPro_feedback.ord_Temp8:= StrToFloat(vLotNoRecord.P_SHORT_CIRCUIT); //盲区差值 fPro_feedback.ord_Temp9:= vLotNoRecord.P_SLICKER_PRESSURE; //出水距离 fPro_feedback.status:= '正常'; if vLotNoRecord.P_OFF_NET=1 then begin WorkLog.MessageInfo('返修数据01'); fPro_feedback.status:= '返修'; fPro_feedback.remark:= vLotNoRecord.P_MESH; //维修备注 // fPro_feedback.station_name:= '维修部'; // fPro_feedback.station_id:= StrToInt(fDevRecord.P_LINE_Num); // fPro_feedback.station_name:= fDevRecord.P_LINE; fPro_feedback.workshop_name:= '维修部'; WorkLog.MessageInfo('提交返修数据02:' + fPro_feedback.remark); end; // Conditions.AddPair('number', fDevRecord.P_LOT); // // //fPro_feedback.equipmentCode:= '[{"code": "M0401"}]'; // fPro_feedback.equipmentCode:= 'M0401'; WorkLog.MessageInfo('提交数据21:' + ''); // prm.RecordToParams(fpro_feedback,Params); // Result := Query_String_list('/prod-api/production/report/add', Params)=''; //insert with TReportHTTPClient.Create do try SendReportRequest(fpro_feedback,sbaseUrl, WebJSon.FP_Token); if (FList_pro_process.Count>0) and (REST_Value(FList_pro_process[fDevRecord.P_LINE_index],'processId')=REST_Value(FList_pro_process[FList_pro_process.Count-1],'processId')) and (List_pro_workorder.Count>0) then //判断是不是最后一个工序 begin RowIndex:= -1; try RowIndex:= StrToInt(REST_Value(List_pro_workorder[0],'id')); WorkLog.MessageInfo('提交数据22:%d',[RowIndex]); if RowIndex>-1 then SendWordOrderRequest(RowIndex,sbaseUrl, WebJSon.FP_Token); except WorkLog.MessageInfo('提交数据23:' + ''); end; end; finally free; end; finally Params.Free; prm.Free; end; Result:=true; end; function TKJSonSave. Thread_Insert_CM_WIP_PROCESS_LINE_HISTORY_NEW(vLotNoRecord:TLotNoRecord;var sError:string):boolean; var ssError:string; bThreadResult:boolean; begin Result:=false; bThreadResult:=false; FThreadId:=0; TThread.CreateAnonymousThread( procedure var bResult:boolean; begin CoInitialize(nil); try bResult:=Insert_CM_WIP_PROCESS_LINE_HISTORY_NEW(vLotNoRecord,ssError); TThread.Synchronize(nil, procedure begin bThreadResult:=bResult; FThreadId:=1; end); finally CoUninitialize; end; end).Start; while FThreadId=0 do Application.ProcessMessages; Result:=bThreadResult; sError:=ssError; end; end.