unit json_webservice; interface uses REST.Client, REST.Types, System.JSON, Winapi.ActiveX, FMX.Forms ,system.NetEncoding, system.SysUtils, System.Classes, uKsoap , uSafeLog; const ACCESS_KEY = '58297a8c75e21d218b1da2c610b6f62c'; baseUrl= 'http://192.168.5.9'; //'http://iot.mrpiot.com:8924'; 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; TPro_feedback = record // id: Integer; // [必填]记录ID workstationId: Integer; // [必填]工作站ID workstationCode: string; // 工作站编号 workstationName: string; // 工作站名称 workorderId: Integer; // [必填]生产工单ID workorderCode: string; // 生产工单编号 workorderName: string; // 生产工单名称 taskId: Integer; // 生产任务ID taskCode: string; // 生产任务编号 itemId: Integer; // [必填]产品物料ID itemCode: string; // [必填]产品物料编码(默认值:'0.00') itemName: string; // [必填]产品物料名称 unitOfMeasure: string; // 计量单位 quantity: Double; // 报工数量(默认值:0.00) assignUsername: string; // 分配用户名 userName: string; // 报工用户名 feedbackTime: string; // 开工时间(日期) status: string; // 状态(默认值:'PREPARE') creator: string; // 创建者(默认值:'') createTime: string; // 创建时间(日期)(默认值:当前时间) updater: string; // 更新者(默认值:'') updateTime: string; // 更新时间(日期)(默认值:当前时间) processId: Integer; // [必填]工序ID processCode: string; // 工序编码 processName: string; // 工序名称 equipmentCode: string; // 设备编号 finishedTime: string; // 完工时间(日期) pauseTime: string; // 暂停时间 pauseReason: string; // 暂停原因 orderQuantity: Double; // 排产数量(默认值:1.00) workOrderQuentity: Double; // 订单数量(默认值:1.00) reportingProgress: Double; // 报工进度(默认值:0.00) deleted: Boolean; // [必填]是否删除(默认值:False) qc_process: string; // 是否合格 ordTemp9: Double; // 参数8 ordTemp8: Double; // 参数8 ordTemp7: Double; // 参数7 ordTemp6: Double; // 参数6 ordTemp5: Double; // 参数5 ordTemp4: Double; // 参数4 ordTemp3: Double; // 参数3 ordTemp2: Double; // 参数2 ordTemp1: Double; // 参数1 tenantId: Integer; // [必填]租户编号(默认值:1) end; TKJSon = 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: TStrings; // 工作站,生产任务表 function REST_Value(Value: String; sKey: String): String; function REST_pro_List(const Value: String; const iValue: Integer; var sError:string):String; function REST_pro_Value(const Value: String; var sError:string):String; function Query_String(ListUrl:String):String; function Query_String_list(ListUrl: String; Params: TStringList = nil): String; function query_user_profile(ListUrl:String; const iValue: Integer; var sError:string):String; function PostJSONWithREST_Login(const username,password:string; 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():TKJSon; var FKJSon:TKJSon; sbaseUrl:String; fPro_feedback: TPro_feedback; implementation function TKJSon. PostJSONWithREST_Login(const username,password:string; var sError:string):String; var RESTClient: TRESTClient; RESTRequest: TRESTRequest; RESTResponse: TRESTResponse; JsonString, JsonString1: string; JsonObject, JsonObject1: TJsonObject; begin ///production/workOrder/list //查询工单列表 /// api/login RESTClient := TRESTClient.Create(sbaseUrl+'/admin-api/system/auth/login'); // RESTClient := TRESTClient.Create('http://192.168.5.9:8080/login'); RESTRequest := TRESTRequest.Create(nil); RESTResponse := TRESTResponse.Create(nil); try sError:= '1'; RESTRequest.Client := RESTClient; RESTRequest.Response := RESTResponse; RESTRequest.Method := rmPOST; // RESTRequest.Method := rmGET; // RESTRequest.AddBody('{"key":"value"}', ctAPPLICATION_JSON); // 修正Content-Type设置方式(移除URL编码) RESTRequest.AddParameter('Content-Type', 'application/json', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTRequest.AddParameter('charset', 'UTF-8', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTRequest.AddParameter('access-control-allow-credentials', 'true', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); //租户编号 RESTRequest.AddParameter('tenant-id', '1', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); // 统一设置请求头 RESTRequest.AddBody(Format('{' +'"tenantName": "春景智能MES",' +'"username": "%s",' +'"password": "%s", ' +'"captchaVerification": "NozBNT2MSDdP2gD1/Eme3saOUQp5e1FPNwbw/Qf9YNjgsGyH+/qwuUng1LC88F4NLX3u8Xw0vN/ttuc+2XtFwg==",' +'"rememberMe": true ' +'}', [username, password]), ctAPPLICATION_JSON); // RESTRequest.AddBody('{"password":"123456"}', ctAPPLICATION_JSON); RESTRequest.Execute; JsonString:= RESTResponse.Content; // 输出完整响应信息 WorkLog.MessageInfo('状态码: %d, 响应: %s', [RESTResponse.StatusCode, JsonString]); // 将字符串解析为 TJsonObject JsonObject := TJsonObject.ParseJSONValue(JsonString) as TJsonObject; if (JsonObject <> nil) then begin if JsonObject.Values['data']<>nil then begin JsonString1:= JsonObject.Values['data'].ToString; WorkLog.MessageInfo('数据: %s', [JsonString1]); JsonObject1 := TJsonObject.ParseJSONValue(JsonString1) as TJsonObject; if JsonObject1.Values['accessToken']<>nil then begin FP_Token:= JsonObject1.Values['accessToken'].Value; Result:= FP_Token; // 访问 JSON 对象中的数据 WorkLog.MessageInfo('token: ' + Result); end; end; end; finally RESTResponse.Free; RESTRequest.Free; RESTClient.Free; end; end; function TKJSon. REST_pro_Value(const Value: String; var sError:string):String; begin Result:= Query_String(Format('/admin-api/system/user/page?username=%s&pageSize=10&pageNo=1',[Value])); end; function TKJSon. REST_pro_List(const Value: String; const iValue: Integer; var sError:string):String; begin case iValue of 0: query_user_profile('/admin-api/mes/md/panhao/list?number=&pageNo=1&pageSize=10', iValue, sError); 1: begin //查工序 FList_pro_process.Clear; query_user_profile('/admin-api/mes/pro/process/list?processCode=&processName=&enableFlag=&pageNo=1&pageSize=10', iValue, sError); end; 2: begin //查用户 List_system_users.Clear; query_user_profile(Format('/admin-api/system/user/page?username=%s&pageSize=10&pageNo=1', [Value]), iValue, sError); end; 3: begin //要工单 List_pro_workorder.Clear; query_user_profile(Format('/admin-api/mes/pro/workorder/list?pageNo=1&pageSize=10&workorderCode=%s', [Value]), iValue, sError); end; 5: begin //查二维码 list_md_workstation.Clear; query_user_profile(Format('/admin-api/mes/md/workstation/list?pageNo=1&pageSize=10%s', [Value]), iValue, sError); end; 6: begin list_pro_task.Clear; //findTaskByOrderCode query_user_profile(Format('/admin-api/mes/pro/task/list?%s', [Value]), iValue, sError); end; end; end; function TKJSon. query_user_profile(ListUrl:String; const iValue: Integer; var sError:string):String; var sTome:string; function GetListValue(sValue: string; Var ListValue:TStrings): Boolean; var I: Integer; sTest: string; JsonObject: TJsonObject; begin JsonObject := TJsonObject.ParseJSONValue(sValue) as TJsonObject; if (JsonObject = nil) then Exit; try // if (JsonObject <> nil) and (JsonObject.Values['data']<>nil) then // begin // if (JsonObject.Values['data'].FindValue('total')<>nil) then // begin // WorkLog.MessageInfo('total: ' + JsonObject.Values['data'].FindValue('total').ToString); // for I := 0 to StrToInt(JsonObject.Values['data'].FindValue('total').ToString) - 1 do // begin // sTest:= JsonObject.Values['data'].FindValue('list').A[I].ToString; // ListValue.Add(sTest); // WorkLog.MessageInfo('list'+IntToStr(I)+': ' + sTest); // end; // end; // end; WorkLog.MessageInfo('TKJSon%d_sValue: %s', [iValue, sValue ]); if JsonObject.Values['taskPage']<>nil then JsonObject:= TJsonObject.ParseJSONValue(JsonObject.Values['taskPage'].ToString) as TJsonObject; if (JsonObject <> nil) and (JsonObject.Values['total']<>nil) then begin WorkLog.MessageInfo('total: ' + JsonObject.Values['total'].ToString); for I := 0 to StrToInt(JsonObject.Values['total'].ToString) - 1 do begin sTest:= JsonObject.Values['list'].A[I].ToString; ListValue.Add(sTest); WorkLog.MessageInfo('list'+IntToStr(I)+': ' + sTest); end; end; finally JsonObject.Free; end; end; begin sTome:= query_String(ListUrl); case iValue of 0: begin end; 1: begin GetListValue(sTome, FList_pro_process); end; 2: begin GetListValue(sTome, List_system_users); end; 3: begin GetListValue(sTome, List_pro_workorder); end; 4: begin GetListValue(sTome, List_Code_workorder); end; 5: begin GetListValue(sTome, List_md_workstation); end; 6: begin GetListValue(sTome, list_pro_task); end; end; end; function TKJSon. Query_String(ListUrl:String):String; var RESTClient: TRESTClient; RESTRequest: TRESTRequest; RESTResponse: TRESTResponse; JsonString: string; JsonObject: TJsonObject; begin if FP_Token='' then begin Result:=''; exit; end; ///production/workOrder/list //查询工单列表 /// api/login /// system/user/profile RESTClient := TRESTClient.Create(sbaseUrl + ListUrl); RESTRequest := TRESTRequest.Create(nil); RESTResponse := TRESTResponse.Create(nil); try RESTRequest.Client := RESTClient; RESTRequest.Response := RESTResponse; // RESTRequest.Method := rmPOST; RESTRequest.Method := rmGET; // RESTRequest.AddBody('{"key":"value"}', ctAPPLICATION_JSON); // 修正Content-Type设置方式(移除URL编码) RESTRequest.AddParameter('Content-Type', 'application/json', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTRequest.AddParameter('charset', 'UTF-8', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTRequest.AddParameter('access-control-allow-credentials', 'true', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTRequest.AddParameter('access-control-allow-origin', '192.168.5.9', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); // 统一设置请求头 RESTRequest.AddParameter('Authorization','Bearer ' + FP_Token, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); //access-control-allow-credentials: true //access-control-allow-origin: http://120.229.200.252 //content-type: application/json;charset=UTF-8 // RESTRequest.AddAuthParameter('Authorization', 'Basic ' + // TNetEncoding.Base64.Encode('dyp:123456'), TRESTRequestParameterKind.pkHTTPHEADER); // RESTRequest.AddBody('{"username":"dyp","password":"123456"}', ctAPPLICATION_JSON); // RESTRequest.AddBody('{"password":"123456"}', ctAPPLICATION_JSON); RESTRequest.Execute; JsonString:= RESTResponse.Content; if RESTResponse.StatusCode = 500 then begin PostJSONWithREST_Login(fDevRecord.FP_User,fDevRecord.FP_Pass,JsonString); Exit; end; // 输出完整响应信息 WorkLog.MessageInfo('状态码: %d, 提交:%s, 响应: %s', [RESTResponse.StatusCode, ListUrl, JsonString]); // 将字符串解析为 TJsonObject JsonObject := TJsonObject.ParseJSONValue(JsonString) as TJsonObject; if (JsonObject <> nil) and (JsonObject.Values['data']<>nil) then begin // FP_Token:= JsonObject.Values['token'].Value; // 访问 JSON 对象中的数据 Result:=JsonObject.Values['data'].ToString; WorkLog.MessageInfo('data: ' + Result); end; // except // on E:Exception do // WorkLog.MessageError('API调用异常: ' + E.Message); // ShowMessage(RESTResponse.Content); finally RESTResponse.Free; RESTRequest.Free; RESTClient.Free; end; end; function TKJSon.Query_String_list(ListUrl: String; Params: TStringList = nil): String; var RESTClient: TRESTClient; RESTRequest: TRESTRequest; RESTResponse: TRESTResponse; JsonValue: TJSONValue; sParams, Param, sEress: string; RetryCount: Integer; JsonBody: TJSONObject; // 新增JSON对象 const MAX_RETRY = 1; // 最大重试次数 begin Result := ''; if FP_Token = '' then Exit; RetryCount := 0; // 记录请求日志 WorkLog.MessageInfo('请求: %s', [ListUrl]); while RetryCount <= MAX_RETRY do try RESTClient := TRESTClient.Create(sbaseUrl + ListUrl); try RESTRequest := TRESTRequest.Create(nil); RESTResponse := TRESTResponse.Create(nil); try RESTRequest.Client := RESTClient; RESTRequest.Response := RESTResponse; RESTRequest.Method := rmPOST; // 添加头部参数 RESTRequest.AddParameter('Authorization', 'Bearer ' + FP_Token, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTRequest.AddParameter('Content-Type', 'application/json', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTRequest.AddParameter('charset', 'UTF-8', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); // 构建JSON请求体 JsonBody := TJSONObject.Create; try if Assigned(Params) then begin for var I := 0 to Params.Count - 1 do begin // 处理 equipmentCode - 解析字符串为 JSON 数组 // if Params.Names[I] = 'equipmentCode' then // begin // try // JsonValue := TJSONObject.ParseJSONValue(Params.ValueFromIndex[I]); // if (JsonValue <> nil) and (JsonValue is TJSONArray) then // JsonBody.AddPair('equipmentCode', JsonValue as TJSONArray); // except // end; // end // else // 添加键值对到JSON对象 JsonBody.AddPair( Params.Names[I], // 参数名 (如 "page") TJSONString.Create(Params.ValueFromIndex[I]) // 参数值 (如 "1") ); end; end; // 设置JSON请求体 RESTRequest.AddBody(JsonBody.ToString, ContentTypeFromString('application/json')); finally JsonBody.Free; // 释放JSON对象 end; sParams := ''; for var i := 0 to RESTRequest.Params.Count - 1 do sParams := sParams + Format('%s=%s; ', [ RESTRequest.Params[i].Name, RESTRequest.Params[i].Value ]); WorkLog.MessageInfo('提交Request: %s', [sParams]); RESTRequest.Execute; // 记录请求日志 WorkLog.MessageInfo('请求: %s, 状态码: %d, 响应: %s', [ListUrl, RESTResponse.StatusCode, RESTResponse.Content]); // 处理特殊状态码 case RESTResponse.StatusCode of 401: // 未授权 begin if RetryCount < MAX_RETRY then begin // 尝试重新登录获取新token if PostJSONWithREST_Login(fDevRecord.FP_User, fDevRecord.FP_Pass, sEress)<>'' then begin Inc(RetryCount); Continue; // 重试请求 end; end; WorkLog.MessageInfo('授权失败: %s', [RESTResponse.Content]); Exit; end; 500: // 服务器错误 begin WorkLog.MessageInfo('服务器错误: %s', [RESTResponse.Content]); Exit; end; end; // 解析JSON响应 JsonValue := TJSONObject.ParseJSONValue(RESTResponse.Content); try if not Assigned(JsonValue) then begin WorkLog.MessageInfo('无效的JSON响应: %s', [RESTResponse.Content]); Exit; end; // 提取data字段 if (JsonValue is TJSONObject) and (TJSONObject(JsonValue).GetValue('data') <> nil) then begin Result := TJSONObject(JsonValue).GetValue('data').ToJSON; WorkLog.MessageInfo('提取的data字段: %s', [Result]); end else begin WorkLog.MessageInfo('响应中缺少data字段: %s', [RESTResponse.Content]); end; finally JsonValue.Free; end; Break; // 成功处理,退出循环 finally FreeAndNil(RESTResponse); FreeAndNil(RESTRequest); end; except on E: Exception do begin WorkLog.MessageInfo('请求执行异常: %s', [E.Message]); Break; end; end; finally FreeAndNil(RESTClient); end; end; function TKJSon. 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; //http://iot.mrpiot.com:8924 function KJSon():TKJSon; begin if FKJSon = nil then FKJSon := TKJSon.Create; Result := FKJSon; end; constructor TKJSon. Create; begin inherited; ClearData(); end; destructor TKJSon. Destroy; begin FList_pro_process.Free; List_system_users.Free; List_pro_workorder.Free; List_Code_workorder.Free; list_md_workstation.Free; list_pro_task.Free; inherited Destroy; end; procedure TKJSon. ClearData(); //清除 廠區 工號 製程 線別 信息 begin FList_pro_process:= TStringList.Create; List_system_users:= TStringList.Create; List_pro_workorder:= TStringList.Create; List_Code_workorder:= TStringList.Create; list_md_workstation:= TStringList.Create; list_pro_task:= TStringList.Create; // P_ORG_CODE:=''; // P_WORK_NUM:=''; // P_PC:=''; // P_LINE:=''; // FP_LINE_NUM:=''; end; function TKJSon. 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 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 TKJSon. 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; procedure InitializeProFeedback(var feedback: TPro_feedback); begin with feedback do begin // id := 0; workstationId := 0; workstationCode := ''; workstationName := ''; workorderId := 0; workorderCode := ''; workorderName := ''; taskId := 0; taskCode := ''; itemId := 0; itemCode := '0.00'; itemName := ''; unitOfMeasure := ''; quantity := 0.00; assignUsername := ''; userName := ''; feedbackTime := ''; status := 'PREPARE'; creator := ''; createTime := DateTimeToStr(Now); updater := ''; updateTime := DateTimeToStr(Now); processId := 0; processCode := ''; processName := ''; equipmentCode := ''; finishedTime := ''; pauseTime := ''; pauseReason := ''; orderQuantity := 1.00; workOrderQuentity := 1.00; reportingProgress := 0.00; deleted := False; ordTemp8 := 0; ordTemp7 := 0; ordTemp6 := 0; ordTemp5 := 0; ordTemp4 := 0; ordTemp3 := 0; ordTemp2 := 0; ordTemp1 := 0; tenantId := 1; end; 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 TKJSon. Insert_CM_WIP_PROCESS_LINE_HISTORY_NEW(vLotNoRecord:TLotNoRecord;var sError:string):boolean; var Params: TStringList; sTemp: String; Conditions: TJSONObject; RowIndex: Integer; 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('workOrderCode='+fDevRecord.P_LOT, 6, sError); end; WorkLog.MessageInfo('提交数据12:' + sError); // if list_md_workstation.Count=0 then exit; if list_pro_task.Count=0 then exit; // sTemp:= list_md_workstation.Strings[0]; InitializeProFeedback(fPro_feedback); WorkLog.MessageInfo('提交数据12:%s,%s',['workOrderCode!' + fDevRecord.P_LOT,'processCode!' + fDevRecord.P_LINE]); // 创建查询条件 Conditions := TJSONObject.Create; try Conditions.AddPair('workorderCode', fDevRecord.P_LOT); Conditions.AddPair('processCode', fDevRecord.P_LINE); // Conditions.AddPair('status', TJSONNumber.Create(0)); // 执行查询 RowIndex := LocateJSONRow(list_pro_task, Conditions); WorkLog.MessageInfo('提交数据13:%d',[RowIndex]); finally Conditions.Free; end; if (RowIndex<0) or (RowIndex>list_pro_task.Count-1) then exit; sTemp:= list_pro_task.Strings[RowIndex]; fPro_feedback.workstationId:= StrToInt(REST_Value(sTemp,'workstationId')); // fPro_feedback.workstationcode:= REST_Value(sTemp,'workstationCode'); 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.assignUsername:= fDevRecord.P_BC; // 分配人账号(字符串) fPro_feedback.userName:= fDevRecord.P_BC; // 操作人姓名(字符串) fPro_feedback.creator:= fDevRecord.P_BC; // 创建人(字符串) fPro_feedback.updater:= fDevRecord.P_BC; // 更新人(字符串) // 时间戳参数 fPro_feedback.feedbackTime:= FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()); // fPro_feedback.feedbackTime反馈时间(日期时间字符串) fPro_feedback.createTime:= FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()); // 创建时间(日期时间字符串) fPro_feedback.updateTime:= FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()); // 更新时间(日期时间字符串) fPro_feedback.finishedTime:= FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()); // 完成时间(日期时间字符串) fPro_feedback.quantity:= 1; // 实际完成数量(浮点数) fPro_feedback.orderQuantity:= 1; // 订单需求数量(浮点数) fPro_feedback.workOrderQuentity:= StrToFloat(REST_Value(sTemp,'quantity')); // 工单计划数量(浮点数) fPro_feedback.reportingProgress:= (fPro_feedback.quantity/fPro_feedback.orderQuantity) * 100; // 进度百分比(浮点数) fPro_feedback.qc_process:= vLotNoRecord.P_DIE_NAME; //是否合格 fPro_feedback.ordTemp1:= vLotNoRecord.P_DIE_USE_NUM; //温度 fPro_feedback.ordTemp2:= vLotNoRecord.P_LINE_SPEED; //距离 fPro_feedback.ordTemp3:= vLotNoRecord.P_ELE_CUR_DENSITY; //回波时间 fPro_feedback.ordTemp4:= vLotNoRecord.P_ELE_AREA1; //幅值 fPro_feedback.ordTemp5:= vLotNoRecord.P_PRODUCT_PRESSURE; //入水盲区 fPro_feedback.ordTemp6:= vLotNoRecord.P_COM_TEMPERATURE; //底噪 if vLotNoRecord.P_SIDE<>'' then fPro_feedback.ordTemp7:= StrToFloat(vLotNoRecord.P_SIDE); //出水盲区 if vLotNoRecord.P_SHORT_CIRCUIT<>'' then fPro_feedback.ordTemp8:= StrToFloat(vLotNoRecord.P_SHORT_CIRCUIT); //盲区差值 //fPro_feedback.equipmentCode:= '[{"code": "M0401"}]'; fPro_feedback.equipmentCode:= 'M0401'; WorkLog.MessageInfo('提交数据21:' + fPro_feedback.workstationname); Params := TStringList.Create; try // Params.Add('id=' + IntToStr(fPro_feedback.id)); // 工作站相关参数 Params.Add('workstationId=' + IntToStr(fPro_feedback.workstationId)); // 工作站唯一标识符(整数) Params.Add('workstationCode=' + fPro_feedback.workstationCode); // 工作站编码(字符串) Params.Add('workstationName=' + fPro_feedback.workstationName); // 工作站名称(字符串) // 工单相关参数 Params.Add('workorderId=' + IntToStr(fPro_feedback.workorderId)); // 工单ID(整数) Params.Add('workorderCode=' + fPro_feedback.workorderCode); // 工单编号(字符串) Params.Add('workorderName=' + fPro_feedback.workorderName); // 工单名称(字符串) // 任务相关参数 Params.Add('taskId=' + IntToStr(fPro_feedback.taskId)); // 任务ID(整数) Params.Add('taskCode=' + fPro_feedback.taskCode); // 任务编码(字符串) // 物料相关参数 Params.Add('itemId=' + IntToStr(fPro_feedback.itemId)); // 物料ID(整数) Params.Add('itemCode=' + fPro_feedback.itemCode); // 物料编码(字符串) Params.Add('itemName=' + fPro_feedback.itemName); // 物料名称(字符串) Params.Add('unitOfMeasure=' + fPro_feedback.unitOfMeasure); // 计量单位(字符串) Params.Add('quantity=' + FloatToStr(fPro_feedback.quantity)); // 实际完成数量(浮点数) Params.Add('orderQuantity=' + FloatToStr(fPro_feedback.orderQuantity));// 订单需求数量(浮点数) Params.Add('workOrderQuentity=' + FloatToStr(fPro_feedback.workOrderQuentity)); // 工单计划数量(浮点数) // 人员信息参数 Params.Add('assignUsername=' + fPro_feedback.assignUsername); // 分配人账号(字符串) Params.Add('userName=' + fPro_feedback.userName); // 操作人姓名(字符串) Params.Add('creator=' + fPro_feedback.creator); // 创建人(字符串) Params.Add('updater=' + fPro_feedback.updater); // 更新人(字符串) // 时间戳参数 Params.Add('feedbackTime=' + fPro_feedback.feedbackTime); // fPro_feedback.feedbackTime反馈时间(日期时间字符串) Params.Add('createTime=' + fPro_feedback.createTime); // 创建时间(日期时间字符串) Params.Add('updateTime=' + fPro_feedback.updateTime); // 更新时间(日期时间字符串) Params.Add('finishedTime=' + fPro_feedback.finishedTime); // 完成时间(日期时间字符串) Params.Add('pauseTime=' + fPro_feedback.pauseTime); // 暂停时间(日期时间字符串) // 状态参数 Params.Add('status=' + fPro_feedback.status); // 任务状态(字符串) Params.Add('deleted=' + BoolToStr(fPro_feedback.deleted)); // 删除标记(布尔值) Params.Add('pauseReason=' + fPro_feedback.pauseReason); // 暂停原因(字符串) // 进度参数 Params.Add('reportingProgress=' + FloatToStr(fPro_feedback.reportingProgress)); // 进度百分比(浮点数) // 工艺参数 Params.Add('processId=' + IntToStr(fPro_feedback.processId)); // 工艺ID(整数) Params.Add('processCode=' + fPro_feedback.processCode); // 工艺编码(字符串) Params.Add('processName=' + fPro_feedback.processName); // 工艺名称(字符串) // 设备参数 Params.Add('equipmentCode=' + fPro_feedback.equipmentCode); // 设备编码(字符串) // 租户参数 Params.Add('tenantId=' + IntToStr(fPro_feedback.tenantId)); // 租户ID(整数) Params.Add('fPro_feedback.qc_process=' + fPro_feedback.qc_process); // 是否合格 // 预留字段(临时变量) Params.Add('ordTemp8=' + FloatToStr(fPro_feedback.ordTemp8)); // 预留字段8(浮点数) Params.Add('ordTemp7=' + FloatToStr(fPro_feedback.ordTemp7)); // 预留字段7(浮点数) Params.Add('ordTemp6=' + FloatToStr(fPro_feedback.ordTemp6)); // 预留字段6(浮点数) Params.Add('ordTemp5=' + FloatToStr(fPro_feedback.ordTemp5)); // 预留字段5(浮点数) Params.Add('ordTemp4=' + FloatToStr(fPro_feedback.ordTemp4)); // 预留字段4(浮点数) Params.Add('ordTemp3=' + FloatToStr(fPro_feedback.ordTemp3)); // 预留字段3(浮点数) Params.Add('ordTemp2=' + FloatToStr(fPro_feedback.ordTemp2)); // 预留字段2(浮点数) Params.Add('ordTemp1=' + FloatToStr(fPro_feedback.ordTemp1)); // 预留字段1(浮点数) Result := Query_String_list('/admin-api/mes/pro/feedback/save', Params)=''; //insert finally Params.Free; end; Result:=true; end; function TKJSon. 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.