unit json_webservice; interface uses REST.Client, REST.Types, System.JSON, Winapi.ActiveX, FMX.Forms ,system.NetEncoding, system.SysUtils, System.Classes, uKsoap , uSafeLog, uWorkOrderRecordUnit, uConfigManager, uLogManager; const ACCESS_KEY = '58297a8c75e21d218b1da2c610b6f62c'; type TWebJSon = class private 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_pro_List(const Value: String; const iValue: Integer; var sError:string):String; FP_Token:string; // function REST_pro_List_xc(const Value: String; const iValue: Integer; var sError:string):String; function REST_pro_Value(const Value: String; var sError:string):String; function REST_pro_Value_xc(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; ValueList: TStrings; var sError:string):String; function PostJSONWithREST_Login(const username,password:string; var sError:string):String; function PostJSONWithREST_Login_xingcheng(const username,password:string; var sError:string):String; procedure ClearData(); //清除 廠區 工號 製程 線別 信息 constructor Create; virtual; destructor Destroy; override; end; function WebJSon():TWebJSon; function GetBaseURL: string; var FWebJSon:TWebJSon; sbaseUrl:String; implementation uses uProReportUnit; function GetBaseURL: string; begin Result := Config.GetServerURL; end; function TWebJSon. PostJSONWithREST_Login(const username,password:string; var sError:string):String; var RESTClient: TRESTClient; RESTRequest: TRESTRequest; RESTResponse: TRESTResponse; JsonString, JsonString1: string; JsonObject, JsonObject1: TJsonObject; StartTime: Int64; begin StartTime := TThread.GetTickCount; try ///production/workOrder/list //查询工单列表 /// api/login // RESTClient := TRESTClient.Create(sbaseUrl+'/admin-api/system/auth/login'); //xingcheng RESTClient := TRESTClient.Create(sbaseUrl + '/prod-api/login'); //yjh 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; if RESTResponse.StatusCode=200 then WorkLog.MessageInfo('url:%s,状态码: %d', [RESTClient.BaseURL, RESTResponse.StatusCode]) else // 输出完整响应信息 WorkLog.MessageInfo('url:%s,状态码: %d, 响应: %s', [RESTClient.BaseURL, RESTResponse.StatusCode, JsonString]); // 将字符串解析为 TJsonObject JsonObject := TJsonObject.ParseJSONValue(JsonString) as TJsonObject; if (JsonObject <> nil) then begin if JsonObject.Values['token']<>nil then begin JsonString1:= JsonObject.Values['token'].ToString; FP_Token:= JsonString1.Replace('"','');//JsonObject1.Values['token'].Value; Result:= FP_Token; WorkLog.MessageInfo('token: ' + Result); end; end; finally try if Assigned(RESTResponse) then LogManager.LogNetworkRequest(sbaseUrl + '/prod-api/login', 'POST', RESTResponse.StatusCode, TThread.GetTickCount - StartTime) else LogManager.LogNetworkRequest(sbaseUrl + '/prod-api/login', 'POST', 0, TThread.GetTickCount - StartTime); except // 静默处理日志记录异常 end; RESTResponse.Free; RESTRequest.Free; RESTClient.Free; end; end; function TWebJSon. PostJSONWithREST_Login_xingcheng(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'); //xingcheng // RESTClient := TRESTClient.Create('http://192.168.5.9:8080/login'); //yjh 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('url:%s,状态码: %d, 响应: %s', [RESTClient.BaseURL, 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 TWebJSon. REST_pro_Value(const Value: String; var sError:string):String; begin Result:= Query_String(Format('/admin-api/system/user/page?username=%s&pageSize=30&pageNo=1',[Value])); end; //function TWebJSon. REST_pro_List(const Value: String; const iValue: Integer; var sError:string):String; //begin // case iValue of // 0: 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; // // query_user_profile('/prod-api/masterdata/material/'+WebJSon.REST_Value(WebJSon.List_pro_workorder.Strings[0],'materialId'), iValue, list_pro_Temp, sError); // // if list_pro_Temp.Count=0 then exit; // // query_user_profile('/prod-api/production/route/'+WebJSon.REST_Value(WebJSon.list_pro_Temp.Strings[0],'routeId'), iValue, FList_pro_process, sError); // // http://192.168.5.9/prod-api/production/route/11 // end; // 2: begin // //查用户 // query_user_profile(Format('/prod-api/system/user/list?userName=%s&pageSize=30&pageNum=1', [Value]), iValue, List_system_users, sError); // end; // 3: begin // //查工单 // query_user_profile(Format('/prod-api/production/workOrder/list?pageNum=1&pageSize=30&number=%s', [Value]), iValue, List_pro_workorder, sError); // end; // 4: begin // //查二维码 // query_user_profile(Format('/prod-api/production/report/list?pageNum=1&pageSize=30%s', [Value]), iValue, List_Code_workorder, sError); // end; // 5: begin // //查二维码 // query_user_profile(Format('/prod-api/production/workOrder/list?pageNum=1&pageSize=30%s', [Value]), iValue, list_md_workstation, sError); // end; // 6: begin // //查报工单 // //findTaskByOrderCode // query_user_profile(Format('/prod-api/production/report/list?%s', [Value]), iValue, list_pro_task, sError); // // end; // 7: begin // //ID查二维码 // //findTaskByOrderCode // query_user_profile(Format('/prod-api/production/report/list?%s', [Value]), iValue, list_pro_Temp, sError); // // end; // 8: begin // //查子工单 // query_user_profile(Format('/prod-api/production/workOrder/getInfoByEntryId/%s', [Value]), iValue, List_pro_workorderEntry, sError); // end; // 9: begin //查所有工序 // query_user_profile('/prod-api/production/process/list?processCode=&processName=&enableFlag=&pageNum=1&pageSize=100', iValue,FList_pro_process, sError); // end; // end; //end; function TWebJSon. REST_pro_Value_xc(const Value: String; var sError:string):String; begin Result:= Query_String(Format('/admin-api/system/user/page?username=%s&pageSize=30&pageNo=1',[Value])); end; //function TWebJSon. REST_pro_List_xc(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=&pageNum=1&pageSize=30', iValue, sError); // 1: begin // //查工序 // FList_pro_process.Clear; // query_user_profile('/admin-api/mes/pro/process/list?processCode=&processName=&enableFlag=&pageNum=1&pageSize=30', iValue, sError); // end; // 2: begin // //查用户 // List_system_users.Clear; // query_user_profile(Format('/admin-api/system/user/page?username=%s&pageNum=1&pageSize=30&pageNo=1', [Value]), iValue, sError); // end; // 3: begin // //要工单 // List_pro_workorder.Clear; // query_user_profile(Format('/admin-api/mes/pro/workorder/list?pageNum=1&pageSize=30&workorderCode=%s', [Value]), iValue, sError); // end; // 5: begin // //查二维码 // list_md_workstation.Clear; // query_user_profile(Format('/admin-api/mes/md/workstation/list?pageNum=1&pageSize=30%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; // 7: begin // // list_pro_temp.Clear; //findTaskByOrderCode // query_user_profile(Format('/admin-api/mes/pro/task/list?%s', [Value]), iValue, sError); // // end; // end; //end; function TWebJSon. query_user_profile(ListUrl:String; const iValue: Integer; ValueList: TStrings; var sError:string):String; var sTome:string; function GetListValue(sValue: string; Var ListValue:TStrings): Boolean; var I: Integer; sTest: string; JsonObject: TJsonObject; ListArray: TJSONArray; begin JsonObject := TJsonObject.ParseJSONValue(sValue) as TJsonObject; if (JsonObject = nil) then Exit; try i:= 0; if JsonObject.Values['taskPage']<>nil then JsonObject:= TJsonObject.ParseJSONValue(JsonObject.Values['taskPage'].ToString) as TJsonObject; if (JsonObject <> nil) then begin if (JsonObject.Values['total']<>nil) then WorkLog.MessageInfo('total: ' + JsonObject.Values['total'].ToString); // WorkLog.MessageInfo('total: ' + sValue); if JsonObject.Values['list']<>nil then begin ListArray:= JsonObject.Values['list'] as TJSONArray; for I := 0 to ListArray.Count - 1 do begin sTest:= ListArray.Get(I).ToString; ListValue.Add(sTest); // WorkLog.MessageInfo('list'+IntToStr(I)+': ' + sTest); end; end; if JsonObject.Values['data']<>nil then begin ListValue.Add(JsonObject.Values['data'].ToString); WorkLog.MessageInfo('list'+IntToStr(I)+': ' + sTest); if (JsonObject.Values['data'].ToString).IndexOf('routeProcessList')>0 then begin JsonObject:= TJsonObject.ParseJSONValue(JsonObject.Values['data'].ToString) as TJsonObject; if JsonObject<>nil then begin WorkLog.MessageInfo('data2:'+JsonObject.ToString); if JsonObject.Values['routeProcessList']<>nil then begin // WorkLog.MessageInfo('routeProcessList1:'+JsonObject.Values['routeProcessList'].ToString); ListArray:= TJsonObject.ParseJSONValue(JsonObject.Values['routeProcessList'].ToString) as TJSONArray; if ListArray<>nil then begin // WorkLog.MessageInfo('routeProcessList2:'+JsonObject.Values['routeProcessList'].ToString); ListValue.Clear; for I := 0 to ListArray.Count - 1 do begin sTest:= ListArray.Get(I).ToString; ListValue.Add(sTest); WorkLog.MessageInfo('list'+IntToStr(I)+': ' + sTest); end; end; end; end; end; end; if JsonObject.Values['rows']<>nil then begin ListArray:= JsonObject.Values['rows'] as TJSONArray; WorkLog.MessageInfo('ListArray:'+ListArray.ToString+': ' + sTest); for I := 0 to ListArray.Count - 1 do begin sTest:= ListArray.Get(I).ToString; ListValue.Add(sTest); WorkLog.MessageInfo('list'+IntToStr(I)+': ' + sTest); end; end; end; if i<1 then begin WorkLog.MessageInfo('TKJSon%d_sValue: %s', [iValue, sValue ]); end; finally JsonObject.Free; end; end; begin sTome:= query_String(ListUrl); ValueList.Clear; GetListValue(sTome, ValueList); // 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; // 7: begin // GetListValue(sTome, list_pro_temp); // end; // 8: begin // GetListValue(sTome, List_pro_workorderEntry); // end; // end; end; function TWebJSon. Query_String(ListUrl:String):String; var RESTClient: TRESTClient; RESTRequest: TRESTRequest; RESTResponse: TRESTResponse; JsonString: string; JsonObject: TJsonObject; i: integer; Param: TRESTRequestParameter; 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', Config.GetCORSOrigin, 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; for i := 0 to RESTRequest.Params.Count - 1 do begin Param := RESTRequest.Params[i]; WorkLog.MessageInfo(Format('[i码:%d] %s: %s', [i, Param.Name, Param.Value])); end; if RESTResponse.StatusCode=200 then WorkLog.MessageInfo('url:%s,状态码: %d', [RESTClient.BaseURL, RESTResponse.StatusCode]) else // 输出完整响应信息 WorkLog.MessageInfo('状态码: %d, 提交:%s, 响应: %s', [RESTResponse.StatusCode, ListUrl, JsonString]); Result:= JsonString; // 将字符串解析为 TJsonObject // JsonObject := TJsonObject.ParseJSONValue(JsonString) as TJsonObject; // if (JsonObject <> nil) then // begin // WorkLog.MessageInfo('data:%s ',[JsonObject.ToString]); // end; // if (JsonObject <> nil) and (JsonObject.Values['rows']<>nil) then // begin // // FP_Token:= JsonObject.Values['token'].Value; // // 访问 JSON 对象中的数据 // Result:=JsonObject.Values['rows'].ToString; // if Result.IndexOf('"list"')<0 then // Result:='{"list":'+Result+',"total":'+JsonObject.Values['total'].ToString+'}'; // // WorkLog.MessageInfo('data:ok '); // end; // except // on E:Exception do // WorkLog.MessageError('API调用异常: ' + E.Message); // ShowMessage(RESTResponse.Content); finally RESTResponse.Free; RESTRequest.Free; RESTClient.Free; end; end; function TWebJSon.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 WebJSon():TWebJSon; begin if FWebJSon = nil then FWebJSon := TWebJSon.Create; sbaseUrl := Config.GetServerURL; Result := FWebJSon; end; constructor TWebJSon. Create; begin inherited; ClearData(); end; destructor TWebJSon. 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; inherited Destroy; end; procedure TWebJSon. 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 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; end.