buli
2022-03-10 a90c9ecfc5118547d0a92b2fee2779eca95e09a5
New Code For PIPL20220310
177个文件已添加
14252 ■■■■■ 已修改文件
force-app/main/default/aura/NewAgencyContact/NewAgencyContact.cmp 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/aura/NewAgencyContact/NewAgencyContact.cmp-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/aura/NewAgencyContact/NewAgencyContact.css 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/aura/NewAgencyContact/NewAgencyContactController.js 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/aura/NewAgencyContact/NewAgencyContactHelper.js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/B_Test.cls 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/B_Test.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/ControllerResponse.cls 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/ControllerResponse.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/DeleteBatch.cls 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/DeleteBatch.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/DeveloperUtility.cls 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/DeveloperUtility.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/FieldInfo.cls 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/FieldInfo.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/FileUploadController.cls 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/FileUploadController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/MetaDataUtility.cls 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/MetaDataUtility.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NFM702ControllerHandler.cls 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NFM702ControllerHandler.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAgencyContactController.cls 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAgencyContactController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditASEActivityController.cls 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditASEActivityController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditAgencyContactController.cls 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditAgencyContactController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditBaseController.cls 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditBaseController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditCampaignMemberController.cls 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditCampaignMemberController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditCaseController.cls 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditCaseController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditContactController.cls 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditContactController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditEventController.cls 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditEventController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditInquiryFormController.cls 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditInquiryFormController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditInspectionReportController.cls 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditInspectionReportController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditQISController.cls 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditQISController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditRepairSubOrderController.cls 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditRepairSubOrderController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditReportController.cls 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditReportController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditTenderinformationController.cls 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewAndEditTenderinformationController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewConsumApplyController.cls 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewConsumApplyController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewConsumApplyEquipSetDetailController.cls 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewConsumApplyEquipSetDetailController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewListOfConsumablesController.cls 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewListOfConsumablesController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewRepairController.cls 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewRepairController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/OnCallController.cls 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/OnCallController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/Option.cls 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/Option.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/PIHelper.cls 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/PIHelper.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/RentalApplyController.cls 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/RentalApplyController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SObjectHelper.cls 445 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SObjectHelper.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SearchContactController.cls 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SearchContactController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SearchLeadController.cls 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SearchLeadController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SoqlHelper.cls 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SoqlHelper.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/TestClass.cls 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/TestClass.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/TestController.cls 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/TestController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/ViewParticipantsController.cls 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/ViewParticipantsController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/B_Test.page 304 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/B_Test.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ConsumApplyUploadPdf.page 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ConsumApplyUploadPdf.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditASEActivity.page 526 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditASEActivity.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditAddress.page 427 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditAddress.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditAgencyContact.page 511 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditAgencyContact.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditCampaignMember.page 421 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditCampaignMember.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditCase.page 442 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditCase.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditContact.page 485 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditContact.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditInquiryForm.page 607 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditInquiryForm.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditInspectionReport.page 436 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditInspectionReport.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditQIS.page 558 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditQIS.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditRepairSubOrder.page 575 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditRepairSubOrder.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditReport.page 590 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditReport.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditTenderinformation.page 434 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewAndEditTenderinformation.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewConsumApply.page 402 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewConsumApply.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewConsumApplyEquipmentSetDetail.page 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewConsumApplyEquipmentSetDetail.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewListOfConsumables.page 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewListOfConsumables.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewOnCall.page 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewOnCall.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewRentalApply.page 387 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewRentalApply.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewRepair.page 327 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewRepair.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewRepairPage.page 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewRepairPage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/RentalApplyUploadPdf.page 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/RentalApplyUploadPdf.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SearchContactPage.page 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SearchContactPage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SearchLeadPage.page 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SearchLeadPage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/TenderInformationUploadPdf.page 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/TenderInformationUploadPdf.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/TestClass.page 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/TestClass.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/TestVfPage.page 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/TestVfPage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/UploadPdf.page 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/UploadPdf.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewASEActivityDecryptInfo.page 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewASEActivityDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewAddressDecryptInfo.page 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewAddressDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewAgencyContactDecryptInfo.page 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewAgencyContactDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewCaseDecryptInfo.page 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewCaseDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewConsumApplyEquipmentSetDetailDecrypt.page 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewConsumApplyEquipmentSetDetailDecrypt.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewContactDecryptInfo.page 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewContactDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewDecryptConsumApply.page 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewDecryptConsumApply.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewEventDecryptInfo.page 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewEventDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewInquiryFormDecryptInfo.page 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewInquiryFormDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewInspectionReportDecryptInfo.page 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewInspectionReportDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewLeadDecryptInfo.page 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewLeadDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewListOfConsumablesDecrypt.page 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewListOfConsumablesDecrypt.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewOnCallDecrypt.page 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewOnCallDecrypt.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewParticipantsDecryptInfo.page 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewParticipantsDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewQISReportDecryptInfo.page 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewQISReportDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewRentalApplyDecrypt.page 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewRentalApplyDecrypt.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewRepairEncrypt.page 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewRepairEncrypt.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewRepairSubOrderDecryptInfo.page 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewRepairSubOrderDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewReportDecryptInfo.page 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewReportDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewTenderinformationDecryptInfo.page 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ViewTenderinformationDecryptInfo.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/triggers/FileAddressTrigger.trigger 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/triggers/FileAddressTrigger.trigger-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/aura/NewAgencyContact/NewAgencyContact.cmp
New file
@@ -0,0 +1,60 @@
<aura:component implements="force:lightningQuickActionWithoutHeader,force:hasRecordId,lightning:actionOverride,lightning:isUrlAddressable" access="global"
                controller="NewAgencyContactController">
    <aura:attribute name = "recordId" type = "Id" default = ""/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <aura:attribute name="layout" type="LayoutDescriberHelper.LayoutWrapper"/>
    <aura:attribute name="record_data" type="Map"/>
    <aura:attribute name="section_names" type="List"/>
    <aura:attribute name="showSpinner" type="Boolean" default = "False"/>
    <aura:attribute name="staticResource" type="Map"/>
    <aura:attribute name="pi_fields_map" type="Map"/>
    <div class="{! v.container_class}">
        <!-- header -->
        <header class="slds-modal__header">
            <h2 id="modal-heading-01" class="slds-modal__title slds-hyphenate">
                Create Agency Contact
            </h2>
        </header>
        <div class="slds-modal__content slds-p-around_medium">
            <aura:if isTrue="{!v.showSpinner}">
                <lightning:spinner alternativeText="Loading" size="medium" />
            </aura:if>
            <lightning:recordEditForm objectApiName="Agency_Contact__c">
                <lightning:accordion activeSectionName="{! v.section_names }" allowMultipleSectionsOpen="true" class="greyyyy" >
                    <aura:iteration items="{!v.layout}" var="section">
                        <aura:if isTrue="{! section.editHeading }">
                            <lightning:accordionSection name="{! section.label }" label="{! section.label }">
                                <aura:iteration items="{! section.layoutColumns}" var="col">
                                    <aura:iteration items="{! col.layoutItems}" var="field">
                                        <aura:if isTrue="{! field.behavior != 'Readonly' }">
                                            <lightning:inputField required="{! field.behavior == 'Required' }" fieldName="{! field.field}" value="{! field.value}" />
                                        </aura:if>
                                    </aura:iteration>
                                </aura:iteration>
                            </lightning:accordionSection>
                        </aura:if>
                    </aura:iteration>
                </lightning:accordion>
            </lightning:recordEditForm>
            <div  style="text-align:center;margin: 5px;">
                <lightning:button class="slds-button slds-button_neutral" label="取消" onclick="{! c.cancelClick }" />
                <lightning:button class="slds-button slds-button_brand" variant="brand" label="保存" onclick="{! c.saveClick }" />
            </div>
        </div>
    </div>
</aura:component>
force-app/main/default/aura/NewAgencyContact/NewAgencyContact.cmp-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<AuraDefinitionBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <description>A Lightning Component Bundle</description>
</AuraDefinitionBundle>
force-app/main/default/aura/NewAgencyContact/NewAgencyContact.css
New file
@@ -0,0 +1,15 @@
.THIS {
}
.THIS .greyyyy .slds-button_reset{
 display: flex;
    align-items: center;
 background: var(--lwc-colorBackground,rgb(243, 242, 242));
 cursor: pointer;
    width: 100%;
    height: 2rem;
    text-align: left;
    color: currentColor;
    font-size: inherit;
    padding: 0 var(--lwc-spacingXSmall,0.5rem);
}
force-app/main/default/aura/NewAgencyContact/NewAgencyContactController.js
New file
@@ -0,0 +1,217 @@
({
    doInit : function(component, event, helper) {
        let rid = component.get('v.recordId');
        let pid = null;
        if(!rid){
            pid = window.location.href.replace("https://","").split("/")[4];
        }
        component.set("v.showSpinner", true);
        helper.CallBackAction(component,'Init',{
            rid : rid,
            pid : pid,
            //rid : component.get('v.recordId'),
            record_type_id : component.get("v.pageReference").state.recordTypeId,
        },function(data){
            component.set("v.showSpinner", false);
            if(data.getState() == "SUCCESS"){
                var rv = data.getReturnValue();
                console.log(rv);
                if(rv.IsSuccess){
                    let layout = JSON.parse(rv.Data.layout);
                    let fields = rv.Data.fields;
                    let staticResource = JSON.parse(rv.Data.staticResource)
                    let section_names = [];
                    section_names = layout.map(s=>s.label);
                    component.set('v.section_names',section_names);
                    let m = {};
                    for(let f of staticResource.PIDetails){
                        m[f.SF_Field_API_Name__c] = f;
                    }
                    component.set('v.pi_fields_map',m);
                    if(rv.Data && rv.Data.data && rv.Data.data.AWS_Data_Id__c){
                        helper.AwsGet(staticResource.queryUrl, {
                            dataId : rv.Data.data.AWS_Data_Id__c
                        }, function(data){
                            console.log('data = ' + data);
                            for(let f of staticResource.PIDetails){
                                if(data.object && data.object.hasOwnProperty(f.AWS_Field_API__c)){
                                    rv.Data.data[f.SF_Field_API_Name__c] = data.object[f.AWS_Field_API__c];
                                    if(data.object.hasOwnProperty(f.AWS_Encrypted_Field_API__c) && data.object[f.AWS_Encrypted_Field_API__c]){
                                        rv.Data.data[f.SF_Field_Encrypted_API__c] = data.object[f.AWS_Encrypted_Field_API__c];
                                    }
                                }
                            }
                            for(let s of layout){
                                for(let c of s.layoutColumns){
                                    for(let item of c.layoutItems){
                                        if(rv.Data.data.hasOwnProperty(item.field)){
                                            item.value = rv.Data.data[item.field];
                                        }
                                        if(fields.hasOwnProperty(item.field)){
                                            item.fi = fields[item.field];
                                        }
                                    }
                                }
                            }
                            component.set('v.record_data',rv.Data.data);
                            component.set('v.layout',layout);
                        }, staticResource.token);
                    }else{
                        for(let s of layout){
                            for(let c of s.layoutColumns){
                                for(let item of c.layoutItems){
                                    if(rv.Data && fields.hasOwnProperty(item.field) && fields[item.field].References && fields[item.field].References.map(m=>m.value).indexOf(rv.Data.pidType) > -1){
                                        item.value = pid;
                                    }
                                }
                            }
                        }
                        component.set('v.layout',layout);
                    }
                    component.set('v.fields',fields);
                    component.set('v.staticResource',staticResource);
                }else{
                    helper.ShowToast({
                        "message" : rv.Message,
                        "type" : "error"
                    });
                }
            }else{
                helper.ShowToast({
                    "message" : "Init error",
                    "type" : "error"
                });
            }
        });
    },
    saveClick : function(component, event, helper){
        let staticResource = component.get('v.staticResource');
        let record_id = component.get('v.recordId');
        let url = staticResource.newUrl;
        let payloadPi = {};
        if (record_id) {
            url = staticResource.updateUrl
            payloadPi['dataId'] = component.get('v.record_data').AWS_Data_Id__c;
        }
        let layout = component.get('v.layout');
        let pi_fields_map = component.get('v.pi_fields_map');
        for(let s of layout){
            for(let c of s.layoutColumns){
                for(let item of c.layoutItems){
                    if(pi_fields_map.hasOwnProperty(item.field)){
                        payloadPi[pi_fields_map[item.field].AWS_Field_API__c] = item.value;
                    }
                }
            }
        }
        component.set("v.showSpinner", true);
        helper.AwsPost(url, [payloadPi], function(result){
            let obj = result.object[0];
            let data = {};
            if(record_id){
                data.Id = record_id;
            }else{
                data.AWS_Data_Id__c = obj.dataId;
            }
            for(let s of layout){
                for(let c of s.layoutColumns){
                    for(let item of c.layoutItems){
                        if(item.field && item.behavior != "Readonly"){
                            if(pi_fields_map.hasOwnProperty(item.field)){
                                data[item.field] = obj[pi_fields_map[item.field].AWS_Field_API__c];
                                data[pi_fields_map[item.field].SF_Field_Encrypted_API__c] = obj[pi_fields_map[item.field].AWS_Encrypted_Field_API__c];
                            }else{
                                data[item.field] = item.value;
                            }
                        }
                    }
                }
            }
            $A.getCallback(function(){
                helper.CallBackAction(component,'Save',{
                    data : data,
                    transId : result.txId
                },function(data){
                    component.set("v.showSpinner", false);
                    if(data.getState() == "SUCCESS"){
                        var rv = data.getReturnValue();
                        console.log(rv);
                        var sfId = rv.Data.recordId;
                        helper.AwsPost(staticResource.transactionUrl,{
                            txId: result.txId,
                            sfRecordId:sfId,
                            isSuccess: rv.IsSuccess ? 1 : 0
                        },function(data){
                            if(rv.IsSuccess){
                                helper.ShowToast({
                                    "message" : "成功",
                                    "type" : "success"
                                });
                                if (record_id){
                                    $A.get("e.force:closeQuickAction").fire();
                                    $A.get('e.force:refreshView').fire();
                                }else{
                                    var sObjectEvent = $A.get("e.force:navigateToSObject");
                                    sObjectEvent.setParams({
                                        "recordId": sfId
                                    })
                                    sObjectEvent.fire();
                                }
                            }else{
                                helper.ShowToast({
                                    "message" : rv.Message,
                                    "type" : "error"
                                });
                            }
                        },staticResource.token);
                    }else{
                        helper.ShowToast({
                            "message" : "Init error",
                            "type" : "error"
                        });
                    }
                });
            })();
        }, staticResource.token);
    },
    cancelClick : function(component, event, helper){
        $A.get("e.force:closeQuickAction").fire();
    },
    scriptsLoaded : function(component, event, helper){}
})
force-app/main/default/aura/NewAgencyContact/NewAgencyContactHelper.js
New file
@@ -0,0 +1,77 @@
({
    CallBackAction  : function(component,action_name,para,callback) {
        var action = component.get("c." + action_name.trimStart().replace("c.",""));
        if(para){
            action.setParams(para);
        }
        if(callback){
            action.setCallback(this,function(data){
                callback(data);
            });
        }
        $A.enqueueAction(action);
    },
    ShowToast : function(paras){
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams(paras);
        toastEvent.fire();
    },
    AwsPost : function(postURL, data ,callback,token){
        let payloadForNewPI = '';
        if(typeof(data) == 'string'){
            payloadForNewPI = data;
        }else{
            payloadForNewPI = JSON.stringify(data);
        }
        fetch(postURL, {
            method: 'POST',
            body: payloadForNewPI,
            headers: {
                'Content-Type': 'application/json',
                'pi-token': token
            }
        }).then((data) => {
            console.log('data=' + JSON.stringify(data));
            return data.json();
        }).then((result) => {
            //this.insertCalloutLog(this.insertModule,postURL,JSON.stringify(payloadForNewPI),JSON.stringify(result),this.successStatus);
            if(callback) callback(result);
        }).catch(error => {
            console.log('error');
            //this.insertCalloutLog(this.insertModule,postURL,JSON.stringify(payloadForNewPI),JSON.stringify(error),this.failStatus);
            console.log(error);
        });
    },
    AwsGet : function(url, data ,callback,token){
        if(typeof(data) == 'string'){
            url += data;
        }else{
            let i = 0;
            for(let p in data){
                url += (i++) ? '&' : '?';
                url += p + '=' + data[p];
            }
        }
        fetch(url, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'pi-token': token
            }
        }).then((data) => {
            console.log('data=' + JSON.stringify(data));
            return data.json();
        }).then((result) => {
            //this.insertCalloutLog(this.insertModule,postURL,JSON.stringify(payloadForNewPI),JSON.stringify(result),this.successStatus);
            if(callback) callback(result);
        }).catch(error => {
            console.log('error');
            //this.insertCalloutLog(this.insertModule,postURL,JSON.stringify(payloadForNewPI),JSON.stringify(error),this.failStatus);
            console.log(error);
        });
    }
})
force-app/main/default/classes/B_Test.cls
New file
@@ -0,0 +1,161 @@
public without sharing class B_Test {
    public Contact newCon { get; set; }
    public Contact searchCon { get; set; }
    public List<LineInfo> lineInfoList { get; set; }
    public String conId { get; set; }
    public String openLine { get; set; }
    private String accountId;
    // SWAG-BB44G7  所在医院id start
    private String HPId;
    private Integer i = 0;
    // SWAG-BB44G7  所在医院id end
    private String nowValue;
    public final string ApiPrefix{get;private set;}
    public String staticResource {get; set;}
    public B_Test() {
        openLine = Apexpages.currentPage().getParameters().get('line');
        accountId = Apexpages.currentPage().getParameters().get('acc');
        // SWAG-BB44G7  检索所在医院id start
        Account temAccount =
            [select id, Parent.parentid from account where id = : accountId];
        if (temAccount.Parent.parentid != null) {
            HPId = temAccount.Parent.parentid;
            i = 1;
        }else{
            HPId = accountId;
            i = 2;
        }
        // SWAG-BB44G7  检索所在医院id end
        nowValue = Apexpages.currentPage().getParameters().get('now');
        lineInfoList = new List<LineInfo>();
        ApiPrefix = 'PIBackApi';
        PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo('Contact');
        staticResource = JSON.serialize(piIntegration);
        System.debug('B_Test');
    }
    public void init() {
        searchCon = new Contact();
        if (nowValue != null && nowValue != '') {
            searchCon = [select Id, Name, Department__c, Type__c, Search_LastName__c, Search_FirstName__c, Phone, Supplement__c,
                         FirstName, LastName
                         from Contact where Id = :nowValue];
            searchCon.Search_LastName__c = searchCon.LastName;
            searchCon.Search_FirstName__c = searchCon.FirstName;
        }
        searchContact();
        newCon = new Contact();
        newCon.AccountId = accountId;
        return;
    }
    public PageReference searchContact() {
        String searchStr = 'select Id, Name, Department__c, Type__c, AccountName__c, Supplement__c, Phone,accountid ';
        searchStr += '        from Contact ';
        searchStr += '       where Isactive__c = \'有效\' ';
        // SWAG-BB44G7  检索所在医院的客户人员 start
        if(i == 1 ){
            searchStr += '         and Account.parent.parentid = :HPId ';
        }
        if(i == 2){
            searchStr += '         and AccountId = :HPId ';
        }
        // searchStr += '         and Account.parent.parentid = :HPId ';
        // SWAG-BB44G7  检索所在医院的客户人员 end
        if (searchCon.Search_LastName__c != null && searchCon.Search_LastName__c != '') {
            searchStr += '     and LastName like \'%' + searchCon.Search_LastName__c + '%\'';
        }
        if (searchCon.Search_FirstName__c != null && searchCon.Search_FirstName__c != '') {
            searchStr += '     and FirstName like \'%' + searchCon.Search_FirstName__c + '%\'';
        }
        system.debug('=====searchStr:' + searchStr);
        List<Contact> searchResult = Database.query(searchStr);
        lineInfoList = new List<LineInfo>();
        Integer line = 0;
        for (Contact con : searchResult) {
            line += 1;
            LineInfo li = new LineInfo(line, con);
            lineInfoList.add(li);
        }
        editClear();
        return null;
    }
    public PageReference editContact() {
        if (conId != null && conId != '') {
            newCon = [select Id, Name, Department__c, Type__c, Search_LastName__c, Search_FirstName__c, Phone, Supplement__c,LastName_Encrypted__c,Phone_Encrypted__c,
                      FirstName, LastName,AWS_Data_Id__c
                      from Contact where Id = :conId];
        }
        System.debug(newCon);
        System.debug('editContact');
        return null;
    }
    public PageReference saveNew()  {
        if (newCon.Search_LastName__c == null || newCon.Search_LastName__c == '') {
            newCon.Search_LastName__c.addError('必须填写。');
            return null;
        }
        newCon.LastName = newCon.Search_LastName__c;
        newCon.FirstName = newCon.Search_FirstName__c;
        upsert newCon;
        searchCon.Search_LastName__c = newCon.LastName;
        searchCon.Search_FirstName__c = newCon.FirstName;
        searchContact();
        return null;
    }
    public PageReference editClear()  {
        newCon = new Contact();
        newCon.AccountId = accountId;
        return null;
    }
    class LineInfo {
        public Integer lineNo { get; set; }
        public Contact con { get; set; }
        public LineInfo(Integer in_line) {
            lineNo = in_line;
            con = new Contact();
        }
        public LineInfo(Integer in_line, Contact in_con) {
            lineNo = in_line;
            con = in_con;
        }
    }
    // @RemoteAction
    // global static Response saveContact(String leadJson,String transId) {
    //     return NewAndEditBaseController.save(new Contact(),leadJson,transId,isNew);
    // }
}
force-app/main/default/classes/B_Test.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/ControllerResponse.cls
New file
@@ -0,0 +1,16 @@
public class ControllerResponse {
    @AuraEnabled
    public boolean IsSuccess{get;set;}
    @AuraEnabled
    public string Message{get;set;}
    @AuraEnabled
    public object Data{get;set;}
    public ControllerResponse(){
        IsSuccess = false;
        Message = '';
    }
}
force-app/main/default/classes/ControllerResponse.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/DeleteBatch.cls
New file
@@ -0,0 +1,20 @@
global class DeleteBatch implements Database.Batchable<sObject>{
    global String queryString;
    global DeleteBatch(String queryString){
        this.queryString = queryString;
    }
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(this.queryString);
    }
    global void execute(Database.BatchableContext BC, List<sObject> scope) {
        try{
            delete scope;
        }Catch(Exception e){
            system.debug('ERROR:' + e.getMessage());
        }
    }
    global void finish(Database.BatchableContext BC) {
    }
}
force-app/main/default/classes/DeleteBatch.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/DeveloperUtility.cls
New file
@@ -0,0 +1,62 @@
public class DeveloperUtility {
    public static List<HTTPResponse> CreateFields(string sobject_name,string [] fields){
        List<HTTPResponse> results = new List<HTTPResponse>();
        for(string f : fields){
            string old_label = f.removeEnd('__c').replace('_',' ');
            string label = old_label + ' Encrypted';
            string name =  label.replace(' ','_')+'__c';
            string description = '';
            system.debug('old_label='+old_label);
            system.debug('label='+label);
            system.debug('name='+name);
            results.add(CreateField(sobject_name,label,name,description,'Text'));
        }
        return results;
    }
    public static HTTPResponse CreateField(string sobject_name, string label,string name,string description,string type){
        HTTP h = new HTTP();
        HTTPRequest req = new HTTPRequest();
        req.setMethod('POST');
        req.setHeader('Content-Type', 'text/xml');
        req.setHeader('SOAPAction', 'create');
        //string sobject_name = 'Contact';
        //string label = 'Title';
        //string name =  'Title'+'_Encrypted__c';
        //string description = '';
        //string type = 'Text';
        boolean typeSpecified = true;
        String b = '<?xml version="1.0" encoding="UTF-8"?>';
        b += '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
        b += '<soapenv:Header>';
        b += '<ns1:SessionHeader soapenv:mustUnderstand="0" xmlns:ns1="http://soap.sforce.com/2006/04/metadata">';
        b += '<ns1:sessionId>' + UserInfo.getSessionId() + '</ns1:sessionId>';
        b += '</ns1:SessionHeader>';
        b += '</soapenv:Header>';
        b += '<soapenv:Body>';
        b += '<create xmlns="http://soap.sforce.com/2006/04/metadata">';
        b += '<metadata xsi:type="ns2:CustomField" xmlns:ns2="http://soap.sforce.com/2006/04/metadata">';
        b += '<type>'+type+'</type>';
        b += '<fullName>'+sobject_name+'.'+name+'</fullName>';
        b += '<label>'+label+'</label>';
        b += '<length>255</length>';
        b += '<description>'+type+'</description>';
        b += '</metadata>';
        b += '</create>';
        b += '</soapenv:Body>';
        b += '</soapenv:Envelope>';
        req.setBody(b);
        req.setCompressed(false);
        req.setEndpoint('https://ocsm--pipl.my.salesforce.com/services/Soap/m/25.0');
        HTTPResponse resp = h.send(req);
        System.debug(resp.getBody());
        return resp;
    }
}
force-app/main/default/classes/DeveloperUtility.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/FieldInfo.cls
New file
@@ -0,0 +1,44 @@
public class FieldInfo
{
    @AuraEnabled public string TypeEnumName{get;set;}
    @AuraEnabled public string Label{get;set;}
    @AuraEnabled public string Name{get;set;}
    @AuraEnabled public object Value{get;set;}
    //@AuraEnabled public schema.DisplayType DisplayType{get;set;}
    @AuraEnabled public List<Option> Options{get;set;}
    @AuraEnabled public boolean IsRequired{get;set;}
    @AuraEnabled public List<Option> References{get;set;}
    public Option GetFirstItemByLabel(string label){
        if(Options == null)return null;
        for(Option lv : Options){
            if(lv!=null&&lv.value == label)return lv;
        }
        return null;
    }
    public Option GetFirstItemByValue(string val){
        if(Options == null)return null;
        for(Option lv : Options){
            if(lv!=null&&lv.value == val)return lv;
        }
        return null;
    }
   public static void CopyTo(FieldInfo source,FieldInfo target)
   {
       if(source == null || target == null )
       {
           return;
       }
       target.TypeEnumName = source.TypeEnumName;
       target.Label = source.Label;
       target.Name = source.Name;
       target.IsRequired = source.IsRequired;
       target.Options = source.Options;
       target.Value = source.Value;
   }
}
force-app/main/default/classes/FieldInfo.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/FileUploadController.cls
New file
@@ -0,0 +1,68 @@
global without sharing class FileUploadController {
    public String staticResource {get; set;}
    public static String sobjectTypeValue = 'Document';
    public String PIPL_Input_PDF_Error_Msg{set;get;}
    public List<FileAddress__c>  fileList{set;get;}
    public Document documentData{set;get;}
    public String parentId{set;get;}
    public FileUploadController(ApexPages.StandardController controller) {
        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Document'));
        SObject obj = controller.getRecord();
        parentId = obj.Id;
        system.debug('Parent Id:'+parentId);
        fileList=getFileds(parentId);
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response saveFile(String fileName,String key,String transId,String parentId){
        FileAddress__c file = new FileAddress__c();
        PIHelper.PIIntegration pI=PIHelper.getPIIntegrationInfo('Document');
        file.DownloadLink__c =pI.undeleteUrl+key+'&fileName='+fileName;
        file.DownloadLink2__c =pI.undeleteUrl+key+'&fileName='+fileName;
        file.FileName__c =fileName;
        file.ViewLink__c =pI.queryUrl+key;
        file.ParentRecordId__c =parentId;
        file.AWS_File_Key__c = key;
        Response response =new Response();
        Savepoint sp = Database.setSavepoint();
        try {
            insert file;
            //4. 插入日志
            //update 20220218 加入新的日志方式
            PIHelper.saveTransLog(sobjectTypeValue,key,transId,file.Id,JSON.serialize(file),'success','');
            response.recordId=file.Id;
            response.status='success';
            return response;
        } catch (Exception e) {
            System.debug('into catch'+e.getMessage());
            PIHelper.saveTransLog(sobjectTypeValue,key,transId,file.Id,JSON.serialize(file),'fail',e.getMessage());
            Database.rollback(sp);
            response.message=e.getMessage();
            response.status='fail';
            return response;
        }
    }
    public PageReference refreshFiles() {
        system.debug('refresh files');
        fileList=getFileds(parentId);
        system.debug('fileList size:'+String.valueOf(fileList.size()));
        system.debug(JSON.serialize(fileList));
        return null;
    }
    public static List<FileAddress__c> getFileds(String parentId){
        if(String.isNotBlank(parentId)){
            return [SELECT Id,ParentRecordId__c, FileName__c,DownloadLink__c,DownloadLink2__c,FileAddress__c.ViewLink__c FROM FileAddress__c where ParentRecordId__c=:parentId order by createddate desc];
        }
        return [SELECT Id, ParentRecordId__c,FileName__c,DownloadLink__c,DownloadLink2__c,FileAddress__c.ViewLink__c FROM FileAddress__c order by createddate desc limit 100];
    }
}
force-app/main/default/classes/FileUploadController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/MetaDataUtility.cls
New file
@@ -0,0 +1,177 @@
public without sharing class MetaDataUtility {
    public static List<Metadata.LayoutSection> GetRecordTypePageLayout(string record_type_id,string objectType){
        Map<string,object> mso = null;
        string layout_name = GetRecordTypePageLayoutName(record_type_id,objectType,UserInfo.getProfileId());
        List<Metadata.LayoutSection>  temp =  GetLayoutSections(objectType,layout_name);
        List<Metadata.LayoutSection>  layoutSectionList = new List<Metadata.LayoutSection>();
        for(Metadata.LayoutSection section : temp){
            boolean a = false;
            for( Metadata.LayoutColumn c: section.layoutColumns){
                //system.debug(c);
                if(c.layoutItems != null && c.layoutItems.size() > 0 ){
                    a = true;
                }
            }
            if(a){
                layoutSectionList.add(section);
            }
        }
        return layoutSectionList;
    }
    /*[{
            "attributes": {
                "type": "Layout",
                "url": "/services/data/v53.0/tooling/sobjects/Layout/00h10000009iAb5AAE"
            },
            "Id": "00h10000009iAb5AAE",
            "Name": ".客户人员レイアウト",
            "TableEnumOrId": "01I10000000er3hEAA",
            "LayoutType": "Standard"
        }]
     */
    public static string GetTableOrEnumId(string objectType){
        Map<string,object> mso = null;
        string resp = null;
        string table_or_enum_id = objectType;
        if(objectType.endsWith('__c')){
            resp = ToolingQuery('SELECT id,DeveloperName from CustomObject where DeveloperName =\''+objectType.replace('__c', '')+'\'');
            if(resp == null){
                system.debug('resp is not ok');
                return null;
            }else{
                mso = (Map<string,object>)Json.deserializeUntyped(resp);
                if(integer.valueOf(mso.get('size')) > 0){
                    table_or_enum_id =  string.valueOf(((Map<string,object>)(((List<object>)mso.get('records'))[0])).get('Id'));
                }else{
                    system.debug('no records');
                    return null;
                }
            }
        }
        return table_or_enum_id;
    }
    public static List<object> GetAllPageLayout(string objectType){
        string resp = null;
        Map<string,object> mso = null;
        string table_or_enum_id =  GetTableOrEnumId(objectType);
        if(string.isBlank(table_or_enum_id)){
            return new List<object>();
        }
        resp = ToolingQuery('SELECT id,name,TableEnumOrId,LayoutType  FROM Layout where TableEnumOrId = \''+table_or_enum_id+'\'');
        if(resp == null){
            system.debug('Layout where TableEnumOrId='+table_or_enum_id+' is null');
            return null;
        }else{
            mso = (Map<string,object>)Json.deserializeUntyped(resp);
            if(integer.valueOf(mso.get('size')) > 0){
                return (List<object>)mso.get('records');
            }else{
                system.debug('no records');
                return new List<object>();
            }
        }
    }
    public static string GetRecordTypePageLayoutName(string record_type_id,string objectType, string profile_id){
        if(!string.isBlank(objectType)){
            List<sobject> lso = [SELECT Id, Name, DeveloperName, SobjectType, IsActive, Description, BusinessProcessId FROM RecordType where SobjectType = :objectType];
            if(lso.size()==0){
                return string.valueOf(((Map<string,object>)(GetAllPageLayout(objectType)[0])).get('Name'));
            }
        }
        // 01210000000QfWdAAK
        string query = 'SELECT Layout.Name, Layout.TableEnumOrId, ProfileId, Profile.Name, RecordTypeId FROM ProfileLayout where id!=null ';
        if(!string.isBlank(record_type_id)){
            query += ' and RecordTypeId = \''+record_type_id+'\'';
        }
        if(!string.isBlank(objectType)){
            query += ' and TableEnumOrId = \''+ GetTableOrEnumId(objectType) +'\'';
        }
        if(!string.isBlank(profile_id)){
            query += ' and ProfileId = \''+profile_id+'\'';
        }
        query += ' order by LastModifiedDate desc ';
        system.debug('query='+query);
        string s = ToolingQuery(query);
        if(string.isBlank(s)){
            system.debug('s is blank');
            return null;
        }else{
            Map<string,object> mso = (Map<string,object>)JSON.deserializeUntyped(s);
            if(integer.valueOf(mso.get('size')) > 0){
                List<object> records = ((List<object>)mso.get('records'));
                mso = (Map<string,object>)(records[0]);
                return string.valueOf(((Map<string,object>)(mso.get('Layout'))).get('Name'));
            }else{
                return null;
            }
        }
    }
    public static string ToolingQuery(string query){
        system.debug('query='+query);
        String baseURL = 'callout:SF_Rest_API/services/data/v41.0/tooling/query?q='+ query.replace(' ', '+');
        HttpResponse resp = null;
        HttpRequest req = new HttpRequest();
        req.setMethod('GET');
        //req.setHeader('Authorization', 'Bearer ' + UserInfo.getsessionid());
        //req.setEndpoint(baseURL);
        req.setEndpoint(baseURL);
        Http client = new Http();
        resp = client.send(req);
        system.debug(resp.getStatus());
        system.debug(resp.getStatusCode());
        if(resp.getStatus() == 'OK'){
            string s = resp.getBody();
            system.debug(resp.getBody());
            return s;
        }else{
            system.debug('status is not ok,error:'+resp.getBody());
            return null;
        }
    }
    public static List<Metadata.LayoutSection> GetLayoutSections(string object_name, string layout_name){
        List<String> componentNameList = new List<String>{object_name+'-'+layout_name};
        //通过Metadata.Operations.retrieve获取metadata
        //Metadata.Layout -> Metadata.LayoutSection -> Metadata.LayoutColumn objects -> Metadata.LayoutItem objects
        List<Metadata.Metadata> componentList = Metadata.Operations.retrieve(Metadata.MetadataType.Layout, componentNameList);
        if(componentList?.size() > 0){
            Metadata.Layout layout = (Metadata.Layout) componentList.get(0);
            List<Metadata.LayoutSection> layoutSectionList = layout.layoutSections;
            return layoutSectionList;
        }
        else{
            return null;
        }
    }
}
force-app/main/default/classes/MetaDataUtility.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NFM702ControllerHandler.cls
New file
@@ -0,0 +1,5 @@
public with sharing class NFM702ControllerHandler {
    public NFM702ControllerHandler() {
    }
}
force-app/main/default/classes/NFM702ControllerHandler.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>41.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAgencyContactController.cls
New file
@@ -0,0 +1,124 @@
public class NewAgencyContactController {
    static string sobjectType = 'Agency_Contact__c';
    @AuraEnabled
    public static ControllerResponse Init(string rid,Id pid, string record_type_id){
        system.debug('rid='+rid+',length='+(rid==null?'null':rid.length()+''));
        system.debug('record_type_id='+record_type_id+',length='+(record_type_id==null?'null':record_type_id.length()+''));
        ControllerResponse res = new ControllerResponse();
        Map<string,object> data = new Map<string,object>();
        res.Data = data;
        Agency_Contact__c ac = null;
        List<Metadata.LayoutSection> layout = null;
        if(string.isBlank(rid)){
            layout = MetaDataUtility.GetRecordTypePageLayout(record_type_id, sobjectType);
            data.put('layout', Json.serialize(layout));
        }else{
            ac = [select RecordTypeId from Agency_Contact__c where id = :rid];
            if(ac == null){
                res.Message = 'id不存在';
                return res;
            }
            record_type_id = ac.RecordTypeId;
            system.debug('record_type_id is fresh ='+ac.RecordTypeId);
            layout = MetaDataUtility.GetRecordTypePageLayout(record_type_id, sobjectType);
            data.put('layout', Json.serialize(layout));
            List<String> fieldApiList = new List<String>();
            /*
            for (LayoutDescriberHelper.LayoutSection ls : layout.layoutSections) {
                for (LayoutDescriberHelper.LayoutField lf : ls.layoutFields) {
                    if (lf.fieldAPI != '') {
                        System.debug('lf.fieldAPI='+lf.fieldAPI+' fieldType='+lf.fieldType);
                        fieldApiList.add(lf.fieldAPI);
                    }
                }
            }
            */
            for( Metadata.LayoutSection s: layout){
               system.debug(s);
                for( Metadata.LayoutColumn c: s.layoutColumns){
                   system.debug(c);
                    if(c.layoutItems != null){
                        for( Metadata.layoutItem item: c.layoutItems){
                           system.debug(item);
                            fieldApiList.add(item.field);
                        }
                    }
                }
            }
            system.debug(fieldApiList);
            ac = database.query(SoqlHelper.DistinctQueryFields('select id, AWS_Data_Id__c , ' + string.join(fieldApiList, ',') + ' from ' + sobjectType + ' where id = :rid'));
            data.put('data', ac);
        }
        if(!string.isBlank(pid)){
            data.put('pidType',pid.getSObjectType().getDescribe().getName());
        }
        data.put('fields', SObjectHelper.GetFieldInfos(sobjectType));
        data.put('staticResource', Json.serialize(PIHelper.getPIIntegrationInfo(sobjectType)));
        res.IsSuccess = true;
        return res;
    }
    @AuraEnabled
    public static ControllerResponse Save(Map<string,object> data,string transId){
        system.debug('data='+data);
        system.debug(!data.containsKey('Id') );
        system.debug( data.get('Id') == null);
        //NewAndEditBaseController.Response response = NewAndEditBaseController.save(new Agency_Contact__c(),Json.serialize(data),transId, !data.containsKey('Id') || data.get('Id') == null );
        //ControllerResponse r = new ControllerResponse();
        Sobject sobj = new Agency_Contact__c();
        ControllerResponse r = SaveCore(sobj, data, transId);
        if (r.IsSuccess) {
            r.Data = new Map<string,object>{
                'recordId'=> sobj.Id
            };
        }
        return r;
    }
    public static ControllerResponse SaveCore(Sobject sobj, Map<string,object> data,string transId ) {
        string sobjectTypeValue = sobj.getSObjectType().getDescribe().getName();
        System.debug('sobjectTypeValue:'+sobjectTypeValue+' Info:' + JSON.serialize(data));
        //1. Prepare the payload for  Lead
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = SobjectHelper.GetFieldMap(sobjectTypeValue);
        ControllerResponse r = new ControllerResponse();
        //2. Save Record Process
        String awsDataId = string.valueOf(data.get('AWS_Data_Id__c'));
        Savepoint sp = Database.setSavepoint();
        try{
            for(string field : fieldAPIToTypeMap.keySet()){
                if(data.containsKey(field)){
                    sobj.put(field, data.get(field));
                }
            }
            upsert sobj;
            PIHelper.saveTransLog(sobjectTypeValue,awsDataId,sobj.Id,transId, Json.serialize(data) ,'success','');
            //System.debug('respzhj = ' + resp);
            r.IsSuccess = true;
            return r;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            r.IsSuccess = false;
            r.message = e.getMessage()+e.getStackTraceString();
            PIHelper.saveTransLog(sobjectTypeValue,awsDataId,sobj.Id,transId, Json.serialize(data) ,'failed',r.message);
            return r;
        }
    }
}
force-app/main/default/classes/NewAgencyContactController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditASEActivityController.cls
New file
@@ -0,0 +1,49 @@
/*
 * Author: Yanan Chen
 * Created Date: 02/14/2022
 * Purpose: Utility class for describe layouts
 * Test Class: NewAndEditASEActivityController
 * History:
 *      02/14/2022 - Yanan Chen - Initial Code.
 *
 * */
global class NewAndEditASEActivityController extends NewAndEditBaseController
{
    // public String contactsInfo {set;get;}//key sfid;value awsid
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public String contactId{set;get;}//For Lookup field
    public String contactAWS{set;get;}
    public String staticResourceContact {get; set;}
    public NewAndEditASEActivityController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('ASEActivity__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        LookUpOverrideFields.add('ReporterASE__c');
        Init(controller.getRecord());
        //添加项
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        SObject obj = controller.getRecord();
        if(obj.Id == null){
            //初始化加载值
            obj.put('OwnerId',UserInfo.getUserId());
        }
        //获取contact 加密ID
        // contactsInfo = LookUpOverrideFieldsMapJson;
        //contact信息(搜索查询query url用)
        ASEActivity__c aseActivity = [Select Id, ReporterASE__c From ASEActivity__c Where Id = : obj.Id];
        if(aseActivity.ReporterASE__c != null){
            Contact contact = [Select Id, AWS_Data_Id__c From Contact Where Id = : aseActivity.ReporterASE__c];
            System.debug('contact : ' + contact );
            contactAWS = contact.AWS_Data_Id__c;
            System.debug('contactAWS : ' + contactAWS );
        }
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
    }
    @RemoteAction
    global static Response saveASEActivity(String leadJson,String transId,Boolean isNew) {
        return save(new ASEActivity__c(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditASEActivityController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditAgencyContactController.cls
New file
@@ -0,0 +1,20 @@
global without sharing class NewAndEditAgencyContactController extends NewAndEditBaseController
{
    public string staticResourceContact{get;private set;}
    global NewAndEditAgencyContactController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Agency_Contact__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        LookUpOverrideFields.add('Contact__c');
        Init(controller.getRecord());
        PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo('Contact');
        staticResourceContact = JSON.serialize(piIntegration);
    }
    @RemoteAction
    global static Response saveContact(String leadJson,String transId,Boolean isNew) {
        return save(new Agency_Contact__c(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditAgencyContactController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditBaseController.cls
New file
@@ -0,0 +1,260 @@
global abstract class NewAndEditBaseController {
    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
    public String awsToken{set;get;}
    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    public String sobjectTypeValue {private set; get;}
    public Boolean isNewMode{set;get;}
    public String rtTypeId {get; set;}
    public String AWSDataId{set;get;}
    // 当前对象所有的加密字段集合
    public List<String> encryptedAPIList{private set;get;}
    // 当前页面中的加密字段集合
    public List<String> layoutEncryptedAPIList{private set;get;}
    //fieldLabel fieldAPI
    public String requiredFieldAPIListStr {get;private set;}
    public String fieldApiListStr {get;private set;}
    public String fieldAPIToLabelMapStr {get;private set;}
    public String staticResource {get; set;}
    public string SobjectName{get{return sobjectTypeValue;}}
    public string SobjectLabel{get;private set;}
    public Map<string,string> AWSToSobjectMap{
        get{
            Map<string,string> temp = new Map<string,string>();
            temp.putAll(AWSToSobjectNonEncryptedMap);
            temp.putAll(AWSToSobjectEncryptedMap);
            return temp;
        }
    }
    public string AWSToSobjectMapJson{get{return JSON.serialize(AWSToSobjectMap);}}
    public Map<string,string> AWSToSobjectNonEncryptedMap{get;private set;}
    public string AWSToSobjectNonEncryptedMapJson{get{return JSON.serialize(AWSToSobjectNonEncryptedMap);}}
    public string AWSToSobjectNonEncryptedMapKeySet{get{return JSON.serialize(new List<string>(AWSToSobjectNonEncryptedMap.keySet()));}}
    public Map<string,string> AWSToSobjectEncryptedMap{get;private set;}
    public string AWSToSobjectEncryptedMapJson{get{return JSON.serialize(AWSToSobjectMap);}}
    public final string ApiPrefix{get;private set;}
    public String sobjectPrefix{get;private set;}
    public String SaveAndNewButtonUrl{get;private set;}
    public List<String> VLookUpFields{get;private set;}
    public String VLookUpFieldsJson{get{return Json.serialize(VLookUpFields);}}
    public List<String> LookUpOverrideFields{get;private set;}
    public string LookUpOverrideFieldsMapJson{get;private set;}
    public NewAndEditBaseController(){
        ApiPrefix = 'PIBackApi';
        AWSToSobjectNonEncryptedMap = new Map<string,string>();
        AWSToSobjectEncryptedMap = new Map<string,string>();
        VLookUpFields = new List<String>();
        layoutEncryptedAPIList = new List<String>();
        LookUpOverrideFields = new List<String>();
    }
    protected virtual void Init(SObject obj){
        sobjectTypeValue = obj.getSObjectType().getDescribe().getName();
        SobjectLabel = obj.getSObjectType().getDescribe().getLabel();
        system.debug('obj='+sobjectTypeValue);
        isNewMode = true;
        List<Sobject> lso = Database.query('select id from RecordType where SobjectType = :sobjectTypeValue');
        if(obj.Id != null){
            isNewMode = false;
            string sql = 'select Id';
            if (lso.size()>0) {
                sql += ',RecordTypeId';
            }
            sql += GenerateReferenceSql()+',AWS_Data_Id__c from '+sobjectTypeValue+' where id =\''+obj.Id+'\' ';
            System.debug('sql='+sql);
            Sobject leadData = Database.query(sql);
            if (lso.size()>0){
                rtTypeId = (String)leadData.get('RecordTypeId');
            }
            AWSDataId = (String)leadData.get('AWS_Data_Id__c');
            Map<String,String> sfIdToAWSIdMap = new Map<String,String>();
            for (string f : LookUpOverrideFields) {
                object o = leadData.get(f);
                System.debug('leadData.get('+f+')='+o);
                if (!String.isBlank(String.valueOf(o))) {
                    sfIdToAWSIdMap.put(String.valueOf(o).subString(0,15), String.valueOf(leadData.getSobject(GetReferenceField(f)).get('AWS_Data_Id__c')));
                }
            }
            LookUpOverrideFieldsMapJson = JSON.serialize(sfIdToAWSIdMap);
        }else{
            rtTypeId = ApexPages.currentPage().getParameters().get('RecordType');
        }
        PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo(sobjectTypeValue);
        layoutEncryptedAPIList = piIntegration.PIFields;
        encryptedAPIList = piIntegration.PIFields;
        staticResource = JSON.serialize(piIntegration);
        sobjectPrefix = piIntegration.sobjectPrefix;
        SaveAndNewButtonUrl = string.format('/{0}/e', new string[]{sobjectPrefix});
        if (lso.size() > 1) {
            SaveAndNewButtonUrl = String.format('/setup/ui/recordtypeselect.jsp?ent={0}&retURL=/{1}/o&save_new_url=/{1}/e?retURL=%2F{1}%2Fo', new String[]{sobjectTypeValue,sobjectPrefix});
        }
        for (PI_Field_Policy_Detail__c PIDetail : piIntegration.PIDetails) {
            AWSToSobjectNonEncryptedMap.put(PIDetail.AWS_Field_API__c, PIDetail.SF_Field_API_Name__c);
            AWSToSobjectEncryptedMap.put(PIDetail.AWS_Encrypted_Field_API__c, PIDetail.SF_Field_Encrypted_API__c);
        }
        System.debug(new List<string>(AWSToSobjectNonEncryptedMap.keySet()));
        system.debug('AWSToSobjectNonEncryptedMapJson=');
        system.debug(AWSToSobjectNonEncryptedMapJson);
        try{
            LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, sobjectTypeValue,'classic');
            layoutSections = LayoutWrapperValue.layoutSections;
            List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
            Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
            List<String> fieldApiList = new List<String>();
            for (LayoutDescriberHelper.LayoutSection ls : layoutSections) {
                for (LayoutDescriberHelper.LayoutField lf : ls.layoutFields) {
                    if (lf.fieldAPI != '') {
                        System.debug('lf.fieldAPI='+lf.fieldAPI+' fieldType='+lf.fieldType);
                        fieldApiList.add(lf.fieldAPI);
                        if (lf.fieldType == 'reference') {
                            VLookUpFields.add(lf.fieldAPI);
                        }
                        //在view解密section中只需显示当前layout中的加密字段
                        // if (encryptedAPIList.contains(lf.fieldAPI)) {
                        //     layoutEncryptedAPIList.add(lf.fieldAPI);
                        // }
                    }
                }
            }
            fieldApiListStr = JSON.serialize(fieldApiList);
            fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
            requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
            //awsToken = AWSServiceTool.getAWSToken();
        }catch(Exception e){
            system.debug('Exception from get layout service:'+e.getmessage());
        }
    }
    public static string GetReferenceField(string f){
        if (f.endsWith('__c')) {
            return f.substring(0,f.length()-1)+'r';
        }
        else if(f.endsWith('Id') || f.endsWith('id') || f.endsWith('ID')) {
            return f.substring(0, f.length()-2);
        }
        else{
            return f;
        }
    }
    public string GenerateReferenceSql(){
        string res ='';
        for (string f : LookUpOverrideFields) {
            res += ','+f+','+GetReferenceField(f)+'.AWS_Data_Id__c';
        }
        return res;
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response save(Sobject sobj, String leadJson,String transId,Boolean isNew) {
        string sobjectTypeValue = sobj.getSObjectType().getDescribe().getName();
        System.debug('sobjectTypeValue:'+sobjectTypeValue+' Info:' + JSON.serialize(leadJson));
        System.debug('json length='+leadJson.length());
        //1. Prepare the payload for  Lead
        Schema.SObjectType leadSchema = schemaMap.get(sobjectTypeValue);
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = leadSchema.getDescribe().fields.getMap();
        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(leadJson);
        Sobject leadInfo = sobj;
        for (String fieldAPI: fieldValueMap.keySet()) {
            system.debug('field API='+fieldAPI);
            Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType();
            String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI));
            system.debug('Field Type:'+fielddataType+' field Value='+fieldValue);
            if(String.valueOf(fielddataType)=='DATE'){
                leadInfo.put(fieldAPI,(String.isBlank(fieldValue)||String.isEmpty(fieldValue))? null:Date.valueOf(fieldValue.replace('/', '-')));
            }else if(String.valueOf(fielddataType)=='DATETIME'){
                if(String.isNotBlank(fieldValue)&&fieldValue.contains('T')){
                    fieldValue = fieldValue.replace('T',' ');
                    leadInfo.put(fieldAPI, Datetime.valueOfGmt(fieldValue));
                }else{
                    leadInfo.put(fieldAPI, null);
                }
            }else if(String.valueof(fielddataType)=='CURRENCY'|| String.valueof(fielddataType)=='PERCENT'||String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){
                leadInfo.put(fieldAPI, (String.isBlank(fieldValue)||String.isEmpty(fieldValue))?0:Decimal.valueOf(fieldValue));
            } else if(String.valueof(fielddataType)=='BOOLEAN'){
                leadInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            }else {
                leadInfo.put(fieldAPI,fieldValue);
            }
        }
        system.debug('for (String fieldAPI: fieldValueMap.keySet()) end');
        //2. Save Record Process
        String status = 'success';
        Response resp = new Response();
        String awsDataId = '';
        Savepoint sp = Database.setSavepoint();
        try{
            System.debug('abcde');
            if(isNew){
                System.debug('leadInfozhj = ' + leadInfo);
                insert leadInfo;
            }else{
                System.debug('into update');
                awsDataId = (String)leadInfo.get('AWS_Data_Id__c');
                if (string.isBlank(awsDataId)) {
                    throw new DMLException('更新时AWS_Data_Id__c不能为空');
                }
                System.debug('awsDataId = ' + awsDataId);
                Sobject[] leads = Database.query('select id from '+sobjectTypeValue+' where AWS_Data_Id__c =:awsDataId');
                System.debug('leads[0].id = ' + leads[0].id);
                leadInfo.put('Id',leads[0].id);//For testing;
                update leadInfo;
            }
            // //saveTransLog(transId, leadInfo.AWS_Data_Id__c, status, '');
            // Transaction_Log__c traLog = new Transaction_Log__c();
            // // AWS_Data_Id__c=AWSDataId,TransId__c=transId,JsonContent__c=leadJson,Status__c=status
            // traLog.AWS_Data_Id__c = AWSDataId;
            // traLog.TransId__c = transId;
            // traLog.JsonContent__c = leadJson;
            // traLog.Status__c = status;
            // insert traLog;
            resp.recordId = leadInfo.Id;
            // resp.message = 'success saveLead';
            resp.status = status;
            PIHelper.saveTransLog(sobjectTypeValue,awsDataId,leadInfo.Id,transId, leadJson ,status,'');
            // (String module,String awsDataId,String sfId, String transId,String content,String status,String respMsg)
            System.debug('respzhj = ' + resp);
            return resp;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            resp.status = 'Exception';
            resp.message = e.getMessage()+e.getStackTraceString();
            PIHelper.saveTransLog(sobjectTypeValue,awsDataId,leadInfo.Id,transId, leadJson ,status,resp.message);
            // PIHelper.saveTransLog(sobjectTypeValue,(String)leadInfo.get('AWS_Data_Id__c'),transId, leadJson,status,e.getStackTraceString());
            return resp;
        }
    }
}
force-app/main/default/classes/NewAndEditBaseController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditCampaignMemberController.cls
New file
@@ -0,0 +1,18 @@
global class NewAndEditCampaignMemberController extends NewAndEditBaseController
{
    public String staticResourceContact {get; set;}
    public NewAndEditCampaignMemberController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('CampaignMember').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        //controller.addFields(fieldList);
        //Init(controller.getRecord());
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
    }
    @RemoteAction
    global static Response saveCampaignMember(String leadJson,String transId,Boolean isNew) {
        return save(new CampaignMember(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditCampaignMemberController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditCaseController.cls
New file
@@ -0,0 +1,146 @@
/*
 * Author: Mingjie Yin
 * Created Date: 02/07/2022
 * Purpose: Utility class for describe layouts
 * Test Class: NewAndEditCaseController
 * History:
 *      02/07/2022 - Mingjie Yin - Initial Code.
 *
 * */
global without sharing class NewAndEditCaseController {
    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
    public String awsToken{set;get;}
    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    public static String sobjectTypeValue = 'Case';
    public Boolean isNewMode{set;get;}
    public String rtTypeId {get; set;}
    public String AWSDataId{set;get;}
    public String contactId{set;get;}//For Lookup field
    public List<String> encryptedAPIList{set;get;}
    public String staticResource {get; set;}
    public String staticResourceContact {get; set;}
    public String requiredFieldAPIListStr {get; set;}
    public String fieldAPIToLabelMapStr {get; set;}
    public String Input_Required_Field_Msg{set;get;}
    public String PIPL_Name_Label{set;get;}
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public String sobjectPrefix{set;get;}
    public String sobjecttypeForFrontEnd{set;get;}
    public String contactsInfo {set;get;}//key sfid;value awsid
    public NewAndEditCaseController(ApexPages.StandardController controller) {
        isNewMode = true;
        Input_Required_Field_Msg = Label.Input_Required_Field_Msg;
        PIPL_Name_Label = Label.PIPL_Name_Label;
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        sobjecttypeForFrontEnd = sobjectTypeValue;
        //获取所有字段
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Case').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        SObject obj = controller.getRecord();
        if(obj.Id != null){
            //更新
            isNewMode = false;
            Case caseData = [select Id,RecordTypeId,AWS_Data_Id__c,ContactId,Contact.AWS_Data_Id__c from Case where id =: obj.Id];
            rtTypeId = caseData.RecordTypeId;
            AWSDataId = caseData.AWS_Data_Id__c;
            System.debug('AWSDataId=' + AWSDataId);
            Map<String,String> sfIdToAWSIdMap = new Map<String,String>();
            if(caseData.ContactId != null){
                sfIdToAWSIdMap.put(String.valueof(caseData.ContactId).subString(0,15),caseData.Contact.AWS_Data_Id__c);
            }
            // sfIdToAWSIdMap.put(String.valueof(caseData.ContactId).subString(0,15),caseData.Contact.AWS_Data_Id__c);
            contactsInfo = JSON.serialize(sfIdToAWSIdMap);
        }else{
            //新建
            rtTypeId = ApexPages.currentPage().getParameters().get('RecordType');
            obj.put('OwnerId',UserInfo.getUserId());
        }
        LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, 'Case','classic');
        layoutSections = LayoutWrapperValue.layoutSections;
        List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
        Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
        requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
        fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
        PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo('Case');
        staticResource = JSON.serialize(piIntegration);
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
        encryptedAPIList = piIntegration.PIFields;
        sobjectPrefix = piIntegration.sobjectPrefix;
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response saveCase(String caseJson,String transId,Boolean isNew) {
        System.debug('Case Info:' + JSON.serialize(caseJson));
        //1. Prepare the payload for  Case
        Schema.SObjectType caseSchema = schemaMap.get(sobjectTypeValue);
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = caseSchema.getDescribe().fields.getMap();
        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(caseJson);
        Case caseInfo = new Case();
        //自定义格式转换
        for (String fieldAPI: fieldValueMap.keySet()) {
            system.debug('field API'+fieldAPI);
            Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType();
            String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI));
            if(String.isBlank(fieldValue)){
                continue;
            }
            if(String.valueOf(fielddataType)=='DATE'){
                caseInfo.put(fieldAPI, Date.valueOf(String.valueOf(fieldValueMap.get(fieldAPI)).replace('/', '-')));
            }else if(String.valueOf(fielddataType)=='DATETIME'){
                String dt = String.valueOf(fieldValueMap.get(fieldAPI));
                if(String.isNotBlank(dt)&&dt.contains('T')){
                    dt = dt.replace('T',' ');
                    caseInfo.put(fieldAPI, Datetime.valueOfGmt(dt));
                }
            }else if(String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){
                caseInfo.put(fieldAPI, Decimal.valueOf(String.valueOf(fieldValueMap.get(fieldAPI))));
            } else if(String.valueof(fielddataType)=='BOOLEAN'){
                caseInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            }else {
                caseInfo.put(fieldAPI, String.valueOf(fieldValueMap.get(fieldAPI)));
            }
        }
        //2. Save Record Process
        String status = 'success';
        Response resp = new Response();
        Savepoint sp = Database.setSavepoint();
        String rid = '';
        try{
            System.debug('abcde');
            if(isNew){
                System.debug('caseInfozhj = ' + caseInfo);
                insert caseInfo;
            }else{
                System.debug('into update');
                String awsDataId = (String)caseInfo.get('AWS_Data_Id__c');
                System.debug('awsDataId = ' + awsDataId);
                Case[] cases = [select id from Case where AWS_Data_Id__c =:awsDataId];
                System.debug('Cases[0].id = ' + cases[0].id);
                caseInfo.put('Id',cases[0].id);//For testing;
                update caseInfo;
            }
            rid=caseInfo.Id;
            PIHelper.saveTransLog(sobjectTypeValue,(String)caseInfo.get('AWS_Data_Id__c'),rid,transId,caseJson ,status,'');
            resp.recordId = caseInfo.Id;
            resp.message = '';
            resp.status = status;
            System.debug('resp from sfdx back-end' + resp);
            return resp;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            status = 'fail';
            PIHelper.saveTransLog(sobjectTypeValue,(String)caseInfo.get('AWS_Data_Id__c'),rid,transId,caseJson,status,e.getMessage());
            resp.message = e.getMessage();
            resp.status = status;
            return resp;
        }
    }
}
force-app/main/default/classes/NewAndEditCaseController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditContactController.cls
New file
@@ -0,0 +1,52 @@
global class NewAndEditContactController extends NewAndEditBaseController
{
    public String unifiedIContactID{set;get;}
    public NewAndEditContactController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Contact').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        Init(controller.getRecord());
        String contactId = controller.getRecord().Id;
        if(contactId != null){
            Contact c = [select UnifiedI_Contact_ID__c from Contact where Id =:contactId ];
            system.debug('Contact c = '+c);
            unifiedIContactID = c.UnifiedI_Contact_ID__c;
        }
        // AWSToSobjectNonEncryptedMap.put('lastName', 'LastName');
        // AWSToSobjectNonEncryptedMap.put('phone', 'Phone');
        // AWSToSobjectNonEncryptedMap.put('email', 'Email');
        // AWSToSobjectNonEncryptedMap.put('medicalStaffFullName', 'MedicalStaff_Full_name__c');
        // AWSToSobjectNonEncryptedMap.put('mobilePhone', 'MobilePhone');
        // AWSToSobjectNonEncryptedMap.put('title', 'Title');
        // AWSToSobjectNonEncryptedMap.put('olyAssistantType', 'OLY_Assistant_Type__c');
        // AWSToSobjectNonEncryptedMap.put('jobCategoryPicklist', 'Job_Category_picklist__c');
        // AWSToSobjectNonEncryptedMap.put('type', 'Type__c');
        // AWSToSobjectNonEncryptedMap.put('contactAddress', 'Contact_address__c');
        // AWSToSobjectNonEncryptedMap.put('contactType', 'ContactType__c');
        // AWSToSobjectNonEncryptedMap.put('doctorDivision1', 'Doctor_Division1__c');
        // AWSToSobjectNonEncryptedMap.put('uniqueNumber', 'UniqueNumber__c');
        // AWSToSobjectEncryptedMap.put('lastNameEncrypt', 'LastName_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('phoneEncrypt', 'Phone_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('emailEncrypt', 'Email_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('medicalStaffFullNameEncrypt', 'MedicalStaff_Full_name_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('mobilePhoneEncrypt', 'MobilePhone_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('titleEncrypt', 'Title_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('olyAssistantTypeEncrypt', 'OLY_Assistant_Type_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('jobCategoryPicklistEncrypt', 'Job_Category_picklist_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('typeEncrypt', 'Type_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('contactAddressEncrypt', 'Contact_address_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('contactTypeEncrypt', 'ContactType_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('doctorDivision1Encrypt', 'Doctor_Division1_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('uniqueNumberEncrypt', 'UniqueNumber_Encrypted__c');
    }
    @RemoteAction
    global static Response saveContact(String leadJson,String transId,Boolean isNew) {
        return save(new Contact(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditContactController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditEventController.cls
New file
@@ -0,0 +1,44 @@
/*
 * Author: Yanan Chen
 * Created Date: 02/15/2022
 * Purpose: Utility class for describe layouts
 * Test Class: NewAndEditEventController
 * History:
 *      02/15/2022 - Yanan Chen - Initial Code.
 *
 * */
global class NewAndEditEventController extends NewAndEditBaseController {
    public String contactAWSIds{set;get;}
    public String staticResources {get; set;}
    public NewAndEditEventController (ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Event').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        Init(controller.getRecord());
        //1. get 访问对象ID
        //query event by controller.getRecord().Id;
        Event event = [SELECT  Id, Visitor1_ID__c, Visitor2_ID__c,  Visitor3_ID__c, Visitor4_ID__c, Visitor5_ID__c FROM Event WHERE Id =:controller.getRecord().Id];
        System.debug('event: ' + event);
        Set<String> contactIds = new Set<String>();
        List<String> conAWSIds = new List<String>();
        contactIds.add(event.Visitor1_ID__c);
        contactIds.add(event.Visitor2_ID__c);
        contactIds.add(event.Visitor3_ID__c);
        contactIds.add(event.Visitor4_ID__c);
        contactIds.add(event.Visitor5_ID__c);
        List<Contact> conListForReport = new List<Contact>([select id,AWS_Data_Id__c from Contact where id in:contactIds and AWS_Data_Id__c!='']);
        for(Contact con:conListForReport){
            conAWSIds.add(con.AWS_Data_Id__c);
        }
        contactAWSIds = JSON.serialize(conAWSIds);
        system.debug('Contact AWSIDs:'+contactAWSIds);
        staticResources = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
    }
    // @RemoteAction
    // global static Response saveEvent(String leadJson,String transId,Boolean isNew) {
    //     return save(new Event(),leadJson,transId,isNew);
    // }
}
force-app/main/default/classes/NewAndEditEventController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditInquiryFormController.cls
New file
@@ -0,0 +1,36 @@
global class NewAndEditInquiryFormController extends NewAndEditBaseController
{
    // public String contactsInfo {set;get;}//key sfid;value awsid
    // public String leadsInfo {set;get;}//key sfid;value awsid
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public String contactId{set;get;}//For Lookup field
    public String leadId{set;get;}//For Lead Lookup
    public String staticResourceContact {get; set;}
    public String staticResourceLead {get; set;}
    public NewAndEditInquiryFormController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Inquiry_form__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        // contact lookup
        LookUpOverrideFields.add('Contact_Name__c');
        LookUpOverrideFields.add('Lead_link__c');
        Init(controller.getRecord());
        //添加项
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        SObject obj = controller.getRecord();
        if(obj.Id == null){
            //初始化加载值
            obj.put('OwnerId',UserInfo.getUserId());
        }
        //contact信息(搜索查询query url用)
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
        //Lead信息(搜索查询query url用)
        staticResourceLead = JSON.serialize(PIHelper.getPIIntegrationInfo('Lead'));
    }
    @RemoteAction
    global static Response saveInquiryForm(String leadJson,String transId,Boolean isNew) {
        return save(new Inquiry_form__c(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditInquiryFormController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditInspectionReportController.cls
New file
@@ -0,0 +1,25 @@
global class NewAndEditInspectionReportController extends NewAndEditBaseController
{
    public NewAndEditInspectionReportController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Inspection_Report__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        Init(controller.getRecord());
        //AWSToSobjectNonEncryptedMap.put('responsiblePersonHP', 'Responsible_Person__c');
        //AWSToSobjectNonEncryptedMap.put('technicianHP', 'Technician_HP__c');
        //AWSToSobjectNonEncryptedMap.put('callerPhone', 'phone__c');
        //AWSToSobjectEncryptedMap.put('responsiblePersonHPEncrypt', 'Responsible_Person_Encrypted__c');
        //AWSToSobjectEncryptedMap.put('technicianHPEncrypt', 'Technician_HP_Encrypted__c');
        //AWSToSobjectEncryptedMap.put('callerPhoneEncrypt', 'phone_Encrypted__c');
        //system.debug('layoutEncryptedAPIList');
    }
    @RemoteAction
    global static Response saveInspectionReport(String leadJson,String transId,Boolean isNew) {
        return save(new Inspection_Report__c(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditInspectionReportController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditQISController.cls
New file
@@ -0,0 +1,12 @@
global with sharing class NewAndEditQISController extends NewAndEditBaseController{
    public NewAndEditQISController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('QIS_Report__c').getDescribe().fields.getMap().keyset());
        controller.addFields(fieldList);
        Init(controller.getRecord());
    }
    @RemoteAction
    global static Response saveQISReport(String leadJson,String transId,Boolean isNew) {
        return save(new QIS_Report__c(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditQISController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditRepairSubOrderController.cls
New file
@@ -0,0 +1,40 @@
/*
 * Author: Yanan Chen
 * Created Date: 02/14/2022
 * Purpose: Utility class for describe layouts
 * Test Class: NewAndEditRepairSubOrderController
 * History:
 *      02/14/2022 - Yanan Chen - Initial Code.
 *
 * */
global class NewAndEditRepairSubOrderController extends NewAndEditBaseController
{
    public String contactsInfo {set;get;}//key sfid;value awsid
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public String contactId{set;get;}//For Lookup field
    public String staticResourceContact {get; set;}
    public NewAndEditRepairSubOrderController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('RepairSubOrder__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        LookUpOverrideFields.add('Receiver__c');
        LookUpOverrideFields.add('Applicanter__c');
        //contactId = LookUpOverrideFieldsMapJson;
        Init(controller.getRecord());
        //添加项
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        SObject obj = controller.getRecord();
        if(obj.Id == null){
            //初始化加载值
            obj.put('OwnerId',UserInfo.getUserId());
        }
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
    }
    @RemoteAction
    global static Response saveRepairSubOrder(String leadJson,String transId,Boolean isNew) {
        return save(new RepairSubOrder__c(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditRepairSubOrderController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditReportController.cls
New file
@@ -0,0 +1,160 @@
global without sharing class NewAndEditReportController {
    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    public static String sobjectTypeValue = 'Report__c';
    public Boolean isNewMode{set;get;}
    public String rtTypeId {get; set;}
    public String AWSDataId{set;get;}
    public String contactId{set;get;}//For Lookup field
    public List<String> encryptedAPIList{set;get;}
    public String staticResource {get; set;}
    public String staticResourceContact {get; set;}
    public String requiredFieldAPIListStr {get; set;}
    public String fieldAPIToLabelMapStr {get; set;}
    public String requiredErrorMsg{set;get;}
    public String contactsInfo {set;get;}
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public String SaveAndNewButtonUrl{get;private set;}
    public String sobjectPrefix{get;private set;}
    public String sobjecttypeForFrontEnd{set;get;}
    public String sobjectId{set;get;}
    public NewAndEditReportController(ApexPages.StandardController controller) {
        sobjectId = [SELECT CustomObjectId,CustomObjectName  FROM CustomObjectUserLicenseMetrics   where CustomObjectName ='Report' limit 1].CustomObjectId;
        isNewMode = true;
        requiredErrorMsg = Label.Input_Required_Field_Msg;
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        sobjecttypeForFrontEnd = sobjectTypeValue;
        //获取所有字段
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Report__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        SObject obj = controller.getRecord();
        if(obj.Id != null){
            //更新
            isNewMode = false;
            Report__c ReportData = [select Id,RecordTypeId,AWS_Data_Id__c,Practitioner1__c,Practitioner1__r.AWS_Data_Id__c,
            Practitioner2__c,Practitioner2__r.AWS_Data_Id__c,Practitioner3__c,Practitioner3__r.AWS_Data_Id__c,
            Practitioner4__c,Practitioner4__r.AWS_Data_Id__c,Practitioner5__c,Practitioner5__r.AWS_Data_Id__c,
            Person_In_Charge__c,Person_In_Charge__r.AWS_Data_Id__c
            from Report__c where id =: obj.Id];
            system.debug('ReportData = ' + ReportData);
            rtTypeId = ReportData.RecordTypeId;
            AWSDataId = ReportData.AWS_Data_Id__c;
            Map<String,String> sfIdToAWSIdMap = new Map<String,String>();
            if(ReportData.Practitioner1__r.Id != null && ReportData.Practitioner1__r.AWS_Data_Id__c!=null){
                sfIdToAWSIdMap.put(String.valueof(ReportData.Practitioner1__r.Id).subString(0,15),ReportData.Practitioner1__r.AWS_Data_Id__c);
            }
            if(ReportData.Practitioner2__r.Id != null && ReportData.Practitioner2__r.AWS_Data_Id__c!=null){
                sfIdToAWSIdMap.put(String.valueof(ReportData.Practitioner2__r.Id).subString(0,15),ReportData.Practitioner2__r.AWS_Data_Id__c);
            }
            if(ReportData.Practitioner3__r.Id != null && ReportData.Practitioner3__r.AWS_Data_Id__c!=null){
                sfIdToAWSIdMap.put(String.valueof(ReportData.Practitioner3__r.Id).subString(0,15),ReportData.Practitioner3__r.AWS_Data_Id__c);
            }
            if(ReportData.Practitioner4__r.Id != null && ReportData.Practitioner4__r.AWS_Data_Id__c!=null){
                sfIdToAWSIdMap.put(String.valueof(ReportData.Practitioner4__r.Id).subString(0,15),ReportData.Practitioner4__r.AWS_Data_Id__c);
            }
            if(ReportData.Practitioner5__r.Id != null && ReportData.Practitioner5__r.AWS_Data_Id__c!=null){
                sfIdToAWSIdMap.put(String.valueof(ReportData.Practitioner5__r.Id).subString(0,15),ReportData.Practitioner5__r.AWS_Data_Id__c);
            }
            if(ReportData.Person_In_Charge__r.Id != null && ReportData.Person_In_Charge__r.AWS_Data_Id__c!=null){
                sfIdToAWSIdMap.put(String.valueof(ReportData.Person_In_Charge__r.Id).subString(0,15),ReportData.Person_In_Charge__r.AWS_Data_Id__c);
            }
            contactsInfo = JSON.serialize(sfIdToAWSIdMap);
        }else{
            //新建
            rtTypeId = ApexPages.currentPage().getParameters().get('RecordType');
            obj.put('OwnerId',UserInfo.getUserId());
        }
        LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, 'Report__c','classic');
        layoutSections = LayoutWrapperValue.layoutSections;
        List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
        Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
        requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
        fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
        PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo('Report__c');
        staticResource = JSON.serialize(piIntegration);
        encryptedAPIList = piIntegration.PIFields;
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
        sobjectPrefix = piIntegration.sobjectPrefix;
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response saveReport(String reportJson,String transId,Boolean isNew) {
        System.debug('report Info:' + JSON.serialize(reportJson));
        //System.debug('rtTypeId: ' + rtTypeId);
        //1. Prepare the payload for  report
        Schema.SObjectType reportSchema = schemaMap.get(sobjectTypeValue);
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = reportSchema.getDescribe().fields.getMap();
        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(reportJson);
        Report__c reportInfo = new Report__c();
        System.debug('自定义格式转换开始');
        //自定义格式转换
        for (String fieldAPI: fieldValueMap.keySet()) {
            System.debug('field API'+fieldAPI);
            Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType();
            String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI));
            if(String.isBlank(fieldValue)){
                continue;
            }
            if(String.valueOf(fielddataType)=='DATE'){
                reportInfo.put(fieldAPI, Date.valueOf(String.valueOf(fieldValueMap.get(fieldAPI)).replace('/', '-')));
            }else if(String.valueOf(fielddataType)=='DATETIME'){
                String dt = String.valueOf(fieldValueMap.get(fieldAPI));
                if(String.isNotBlank(dt)&&dt.contains('T')){
                    dt = dt.replace('T',' ');
                    reportInfo.put(fieldAPI, Datetime.valueOfGmt(dt));
                }
            }else if(String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){
                reportInfo.put(fieldAPI, Decimal.valueOf(String.valueOf(fieldValueMap.get(fieldAPI))));
            } else if(String.valueof(fielddataType)=='BOOLEAN'){
                reportInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            }else {
                reportInfo.put(fieldAPI, String.valueOf(fieldValueMap.get(fieldAPI)));
            }
        }
        System.debug('自定义格式转换结束');
        //2. Save Record Process
        String status = 'success';
        Response resp = new Response();
        Savepoint sp = Database.setSavepoint();
        String rid = '';
        try{
            if(isNew){
                System.debug('reportInfo = ' + reportInfo);
                insert reportInfo;
            }else{
                System.debug('into update');
                String awsDataId = (String)reportInfo.get('AWS_Data_Id__c');
                System.debug('awsDataId = ' + awsDataId);
                report__c[] reports = [select id from report__c where AWS_Data_Id__c =:awsDataId];
                System.debug('reports[0].id = ' + reports[0].id);
                reportInfo.put('Id',reports[0].id);//For testing;
                update reportInfo;
            }
            rid=reportInfo.Id;
            PIHelper.saveTransLog(sobjectTypeValue,(String)reportInfo.get('AWS_Data_Id__c'),rid,transId,reportJson ,status,'');
            resp.recordId = reportInfo.Id;
            // resp.message = 'success savereport';
            resp.status = status;
            return resp;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            status = 'fail';
            PIHelper.saveTransLog(sobjectTypeValue,(String)reportInfo.get('AWS_Data_Id__c'),rid,transId,reportJson,status,e.getMessage());
            resp.message = e.getMessage();
            resp.status = status;
            return resp;
        }
    }
}
force-app/main/default/classes/NewAndEditReportController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewAndEditTenderinformationController.cls
New file
@@ -0,0 +1,45 @@
global class NewAndEditTenderinformationController extends NewAndEditBaseController
{
    public NewAndEditTenderinformationController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Tender_information__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        Init(controller.getRecord());
        // AWSToSobjectNonEncryptedMap.put('lastName', 'LastName');
        // AWSToSobjectNonEncryptedMap.put('phone', 'Phone');
        // AWSToSobjectNonEncryptedMap.put('email', 'Email');
        // AWSToSobjectNonEncryptedMap.put('medicalStaffFullName', 'MedicalStaff_Full_name__c');
        // AWSToSobjectNonEncryptedMap.put('mobilePhone', 'MobilePhone');
        // AWSToSobjectNonEncryptedMap.put('title', 'Title');
        // AWSToSobjectNonEncryptedMap.put('olyAssistantType', 'OLY_Assistant_Type__c');
        // AWSToSobjectNonEncryptedMap.put('jobCategoryPicklist', 'Job_Category_picklist__c');
        // AWSToSobjectNonEncryptedMap.put('type', 'Type__c');
        // AWSToSobjectNonEncryptedMap.put('contactAddress', 'Contact_address__c');
        // AWSToSobjectNonEncryptedMap.put('contactType', 'ContactType__c');
        // AWSToSobjectNonEncryptedMap.put('doctorDivision1', 'Doctor_Division1__c');
        // AWSToSobjectNonEncryptedMap.put('uniqueNumber', 'UniqueNumber__c');
        // AWSToSobjectEncryptedMap.put('lastNameEncrypt', 'LastName_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('phoneEncrypt', 'Phone_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('emailEncrypt', 'Email_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('medicalStaffFullNameEncrypt', 'MedicalStaff_Full_name_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('mobilePhoneEncrypt', 'MobilePhone_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('titleEncrypt', 'Title_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('olyAssistantTypeEncrypt', 'OLY_Assistant_Type_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('jobCategoryPicklistEncrypt', 'Job_Category_picklist_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('typeEncrypt', 'Type_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('contactAddressEncrypt', 'Contact_address_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('contactTypeEncrypt', 'ContactType_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('doctorDivision1Encrypt', 'Doctor_Division1_Encrypted__c');
        // AWSToSobjectEncryptedMap.put('uniqueNumberEncrypt', 'UniqueNumber_Encrypted__c');
    }
    @RemoteAction
    global static Response saveTenderinformation(String leadJson,String transId,Boolean isNew) {
        return save(new Tender_information__c(),leadJson,transId,isNew);
    }
}
force-app/main/default/classes/NewAndEditTenderinformationController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewConsumApplyController.cls
New file
@@ -0,0 +1,139 @@
/**
 * @description       :
 * @author            : ChangeMeIn@UserSettingsUnder.SFDoc
 * @group             :
 * @last modified on  : 03-10-2022
 * @last modified by  : ChangeMeIn@UserSettingsUnder.SFDoc
**/
global without sharing class NewConsumApplyController {
    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
    public String awsToken{set;get;}
    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    public static String sobjectTypeValue = 'Consum_Apply__c';
    public Boolean isNewMode{set;get;}
    public String rtTypeId {get; set;}
    public String AWSDataId{set;get;}
    public List<String> encryptedAPIList{set;get;}
    public String staticResource {get; set;}
    public String staticResourceContact {get; set;}
    public String requiredFieldAPIListStr {get; set;}
    public String fieldAPIToLabelMapStr {get; set;}
    public String Input_Required_Field_Msg{set;get;}
    public String requiredErrorMsg{set;get;}
    public String contactsInfo {set;get;}
    public String contactId{set;get;}
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public NewConsumApplyController(ApexPages.StandardController controller) {
        isNewMode = true;
        Input_Required_Field_Msg = Label.Input_Required_Field_Msg;
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        //获取所有字段
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Consum_Apply__c').getDescribe().fields.getMap().keyset());
        controller.addFields(fieldList);
        SObject obj = controller.getRecord();
        if(obj.Id != null){
            //更新
            isNewMode = false;
            Consum_Apply__c consumApplyData = [select Id,RecordTypeId,AWS_Data_Id__c,Loaner_medical_Staff__c,Loaner_medical_Staff__r.AWS_Data_Id__c from Consum_Apply__c where id =: obj.Id];
            rtTypeId = consumApplyData.RecordTypeId;
            AWSDataId = consumApplyData.AWS_Data_Id__c;
            Map<String,String> sfIdToAWSIdMap = new Map<String,String>();
            // if(consumApplyData.Loaner_medical_Staff__c != null && consumApplyData.Loaner_medical_Staff__c != '') {
            if(consumApplyData.Loaner_medical_Staff__r.Id != null){
                sfIdToAWSIdMap.put(String.valueof(consumApplyData.Loaner_medical_Staff__r.Id).subString(0,15),consumApplyData.Loaner_medical_Staff__r.AWS_Data_Id__c);
            }
            // sfIdToAWSIdMap.put(String.valueof(consumApplyData.Contact_Name__r.Id).subString(0,15),consumApplyData.Loaner_medical_Staff__r.AWS_Data_Id__c);
            contactsInfo = JSON.serialize(sfIdToAWSIdMap);
        }else{
            //新建
            rtTypeId = ApexPages.currentPage().getParameters().get('RecordType');
            obj.put('OwnerId',UserInfo.getUserId());
        }
        LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, 'Consum_Apply__c','classic');
        layoutSections = LayoutWrapperValue.layoutSections;
        List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
        Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
        requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
        fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Consum_Apply__c'));
        encryptedAPIList = PIHelper.getPIIntegrationInfo('Consum_Apply__c').PIFields;
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response saveConsumApply(String consumApplyJson,String transId,Boolean isNew) {
        System.debug('Consum_Apply__c Info:' + JSON.serialize(consumApplyJson));
        //1. Prepare the payload for  Consum_Apply__c
        Schema.SObjectType consumApplySchema = schemaMap.get(sobjectTypeValue);
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = consumApplySchema.getDescribe().fields.getMap();
        system.debug(fieldAPIToTypeMap);
        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(consumApplyJson);
        Consum_Apply__c consumApplyInfo = new Consum_Apply__c();
        //自定义格式转换
        for (String fieldAPI: fieldValueMap.keySet()) {
            system.debug('field API='+fieldAPI);
            Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType();
            String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI));
            system.debug('Field Type:'+fielddataType+' field Value='+fieldValue);
            if(String.valueOf(fielddataType)=='DATE'){
                consumApplyInfo.put(fieldAPI,(String.isBlank(fieldValue)||String.isEmpty(fieldValue))? null:Date.valueOf(fieldValue.replace('/', '-')));
            }else if(String.valueOf(fielddataType)=='DATETIME'){
                if(String.isNotBlank(fieldValue)&&fieldValue.contains('T')){
                    fieldValue = fieldValue.replace('T',' ');
                    consumApplyInfo.put(fieldAPI, Datetime.valueOfGmt(fieldValue));
                }else{
                    consumApplyInfo.put(fieldAPI, null);
                }
            }else if(String.valueof(fielddataType)=='CURRENCY'|| String.valueof(fielddataType)=='PERCENT'||String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){
                consumApplyInfo.put(fieldAPI, (String.isBlank(fieldValue)||String.isEmpty(fieldValue))?0:Decimal.valueOf(fieldValue));
            } else if(String.valueof(fielddataType)=='BOOLEAN'){
                consumApplyInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            }else {
                consumApplyInfo.put(fieldAPI,fieldValue);
            }
        }
        //2. Save Record Process
        String status = 'success';
        Response resp = new Response();
        Savepoint sp = Database.setSavepoint();
        String rid = '';
        try{
            System.debug('abcde');
            if(isNew){
                System.debug('consumApplyInfozhj = ' + consumApplyInfo);
                insert consumApplyInfo;
                System.debug('consumApplyInfo.Id' + consumApplyInfo.Id);
            }else{
                System.debug('into update');
                String awsDataId = (String)consumApplyInfo.get('AWS_Data_Id__c');
                System.debug('awsDataId = ' + awsDataId);
                Consum_Apply__c[] ConsumApplys = [select id from Consum_Apply__c where AWS_Data_Id__c =:awsDataId];
                System.debug('ConsumApplys[0].id = ' + ConsumApplys[0].id);
                consumApplyInfo.put('Id',ConsumApplys[0].id);//For testing;
                update consumApplyInfo;
            }
            rid=consumApplyInfo.Id;
            PIHelper.saveTransLog(sobjectTypeValue,rid,transId, (String)consumApplyInfo.get('AWS_Data_Id__c'),consumApplyJson ,status,'');
            resp.recordId = consumApplyInfo.Id;
            resp.message = '';
            resp.status = status;
            System.debug('resp from sfdx back-end' + resp);
            return resp;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            status = 'fail';
            PIHelper.saveTransLog(sobjectTypeValue,rid,transId, (String)consumApplyInfo.get('AWS_Data_Id__c'),consumApplyJson,status,e.getMessage());
            resp.message = e.getMessage();
            resp.status = status;
            return resp;
        }
    }
}
force-app/main/default/classes/NewConsumApplyController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewConsumApplyEquipSetDetailController.cls
New file
@@ -0,0 +1,125 @@
global without sharing class NewConsumApplyEquipSetDetailController {
    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
    public String awsToken{set;get;}
    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    public static String sobjectTypeValue = 'Consum_Apply_Equipment_Set_Detail__c';
    public Boolean isNewMode{set;get;}
    public String rtTypeId {get; set;}
    public String AWSDataId{set;get;}
    public List<String> encryptedAPIList{set;get;}
    public String staticResource {get; set;}
    public String requiredFieldAPIListStr {get; set;}
    public String fieldAPIToLabelMapStr {get; set;}
    public String Input_Required_Field_Msg{set;get;}
    public String requiredErrorMsg{set;get;}
    public String sobjecttypeForFrontEnd{set;get;}
    public String sobjectPrefix{set;get;}
    public NewConsumApplyEquipSetDetailController(ApexPages.StandardController controller) {
        isNewMode = true;
        Input_Required_Field_Msg = Label.Input_Required_Field_Msg;
        sobjecttypeForFrontEnd = sobjectTypeValue;
        //获取所有字段
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Consum_Apply_Equipment_Set_Detail__c').getDescribe().fields.getMap().keyset());
        controller.addFields(fieldList);
        SObject obj = controller.getRecord();
        if(obj.Id != null){
            //更新
            isNewMode = false;
            Consum_Apply_Equipment_Set_Detail__c consumApplyData = [select Id,AWS_Data_Id__c from Consum_Apply_Equipment_Set_Detail__c where id =: obj.Id];
            AWSDataId = consumApplyData.AWS_Data_Id__c;
        }else{
            //新建
            rtTypeId = ApexPages.currentPage().getParameters().get('RecordType');
        }
        LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, 'Consum_Apply_Equipment_Set_Detail__c','classic');
        layoutSections = LayoutWrapperValue.layoutSections;
        List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
        Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
        requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
        fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
        PIHelper.PIIntegration piIntegration =PIHelper.getPIIntegrationInfo('Consum_Apply_Equipment_Set_Detail__c');
        staticResource = JSON.serialize(piIntegration);
        encryptedAPIList = piIntegration.PIFields;
        sobjectPrefix = piIntegration.sobjectPrefix;
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response saveConsumApply(String consumApplyJson,String transId,Boolean isNew) {
        System.debug('Consum_Apply_Equipment_Set_Detail__c Info:' + JSON.serialize(consumApplyJson));
        //1. Prepare the payload for  Consum_Apply_Equipment_Set_Detail__c
        Schema.SObjectType consumApplySchema = schemaMap.get(sobjectTypeValue);
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = consumApplySchema.getDescribe().fields.getMap();
        system.debug(fieldAPIToTypeMap);
        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(consumApplyJson);
        Consum_Apply_Equipment_Set_Detail__c consumApplyInfo = new Consum_Apply_Equipment_Set_Detail__c();
        //自定义格式转换
        for (String fieldAPI: fieldValueMap.keySet()) {
            system.debug('field API'+fieldAPI);
            String fieldValue = String.valueOf(fieldAPIToTypeMap.get(fieldAPI));
            if(String.isBlank(fieldValue)){
                continue;
            }
            Schema.DescribeFieldResult fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe();
            Schema.DisplayType fieldDatas = fielddataType.getType();
            if(String.valueOf(fielddatas)=='DATE'){
                consumApplyInfo.put(fieldAPI, Date.valueOf(String.valueOf(fieldValueMap.get(fieldAPI)).replace('/', '-')));
            }else if(String.valueOf(fielddatas)=='DATETIME'){
                String dt = String.valueOf(fieldValueMap.get(fieldAPI));
                if(String.isNotBlank(dt)&&dt.contains('T')){
                    dt = dt.replace('T',' ');
                    consumApplyInfo.put(fieldAPI, Datetime.valueOfGmt(dt));
                }
            }else if(String.valueOf(fielddatas)=='Number'||String.valueOf(fielddatas)=='DOUBLE'){
                // ||String.valueOf(fielddatas)=='Decimal'
                consumApplyInfo.put(fieldAPI, Decimal.valueOf(String.valueOf(fieldValueMap.get(fieldAPI))));
            } else if(String.valueof(fielddatas)=='BOOLEAN'){
                consumApplyInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            }else {
                consumApplyInfo.put(fieldAPI, String.valueOf(fieldValueMap.get(fieldAPI)));
            }
        }
        //2. Save Record Process
        String status = 'success';
        Response resp = new Response();
        Savepoint sp = Database.setSavepoint();
        String rid = '';
        try{
            System.debug('abcde');
            if(isNew){
                System.debug('consumApplyInfozhj = ' + consumApplyInfo);
                insert consumApplyInfo;
                System.debug('consumApplyInfo.Id' + consumApplyInfo.Id);
            }else{
                System.debug('into update');
                String awsDataId = (String)consumApplyInfo.get('AWS_Data_Id__c');
                System.debug('awsDataId = ' + awsDataId);
                Consum_Apply_Equipment_Set_Detail__c[] ConsumApplys = [select id from Consum_Apply_Equipment_Set_Detail__c where AWS_Data_Id__c =:awsDataId];
                System.debug('ConsumApplys[0].id = ' + ConsumApplys[0].id);
                consumApplyInfo.put('Id',ConsumApplys[0].id);//For testing;
                update consumApplyInfo;
            }
            rid=consumApplyInfo.Id;
            PIHelper.saveTransLog(sobjectTypeValue,(String)consumApplyInfo.get('AWS_Data_Id__c'),rid,transId,consumApplyJson,status,'');
            resp.recordId = consumApplyInfo.Id;
            resp.message = 'success saveConsumApply';
            resp.status = status;
            System.debug('respzhj = ' + resp);
            return resp;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            status = 'fail';
            PIHelper.saveTransLog(sobjectTypeValue,(String)consumApplyInfo.get('AWS_Data_Id__c'),rid,transId,consumApplyJson,status,e.getMessage());
            resp.message = e.getMessage();
            resp.status = status;
            return resp;
        }
    }
}
force-app/main/default/classes/NewConsumApplyEquipSetDetailController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewListOfConsumablesController.cls
New file
@@ -0,0 +1,3 @@
public class NewListOfConsumablesController {
}
force-app/main/default/classes/NewListOfConsumablesController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/NewRepairController.cls
New file
@@ -0,0 +1,148 @@
/*
 *@Description:
 *@Author: Dennis Rodman
 *@Date: 2022-03-10 10:26:47
*/
global without sharing class NewRepairController {
    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
    public String awsToken{set;get;}
    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    public static String sobjectTypeValue = 'Repair__c';
    public Boolean isNewMode{set;get;}
    public String rtTypeId {get; set;}
    public String AWSDataId{set;get;}
    public String DecryptAWSDataId{set;get;}
    public String ContactAWSDataId{set;get;}
    public List<String> encryptedAPIList{set;get;}
    public String staticResource {get; set;}
    public String staticResourceContact {get; set;}
    public String staticResourceAddress {get; set;}
    public String requiredFieldAPIListStr {get; set;}
    public String fieldAPIToLabelMapStr {get; set;}
    public String Input_Required_Field_Msg{set;get;}
    public String PIPL_Name_Label{set;get;}
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public String sobjectPrefix{set;get;}
    public String sobjecttypeForFrontEnd{set;get;}
    public String sobjectId{set;get;}
    public NewRepairController(ApexPages.StandardController controller) {
        sobjectId = [SELECT CustomObjectId,CustomObjectName  FROM CustomObjectUserLicenseMetrics   where CustomObjectName ='Repair' limit 1].CustomObjectId;
        isNewMode = true;
        Input_Required_Field_Msg = Label.Input_Required_Field_Msg;
        PIPL_Name_Label = Label.PIPL_Name_Label;
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        sobjecttypeForFrontEnd = sobjectTypeValue;
        //获取所有字段
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Repair__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        SObject obj = controller.getRecord();
        if(obj.Id != null){
            //更新
            isNewMode = false;
            Repair__c repairData = [select Id,RecordTypeId,AWS_Data_Id__c,Address_AWS_Data_Id__c,Contact_AWS_Data_Id__c,Address_Contacts_Encrypt__c,Address_Contacts_Name_Encrypt__c,Address_Telephone_Encrypt__c,Address_ZipCode_Encrypt__c,Detailed_Address_Encrypt__c from Repair__c where id =: obj.Id];
            rtTypeId = repairData.RecordTypeId;
            AWSDataId = repairData.AWS_Data_Id__c;
            DecryptAWSDataId = String.valueOf(repairData.Address_AWS_Data_Id__c);
            ContactAWSDataId = String.valueOf(repairData.Contact_AWS_Data_Id__c);
        }else{
            //新建
            rtTypeId = ApexPages.currentPage().getParameters().get('RecordType');
            if(String.isBlank(rtTypeId)||String.isEmpty(rtTypeId)){
                List<RecordType> rtList = new List<RecordType>([select Id,DeveloperName from RecordType  where SobjectType ='Repair__c' and DeveloperName ='Repair']);
                rtTypeId = rtList[0].Id;
            }
        }
        LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, 'Repair__c','classic');
        layoutSections = LayoutWrapperValue.layoutSections;
        List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
        Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
        requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
        fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
        PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo('Repair__c');
        PIHelper.PIIntegration piIntegrationAddress = PIHelper.getPIIntegrationInfo('Address__c');
        PIHelper.PIIntegration piIntegrationContact = PIHelper.getPIIntegrationInfo('Contact');
        staticResource = JSON.serialize(piIntegration);
        staticResourceAddress = JSON.serialize(piIntegrationAddress);
        staticResourceContact = JSON.serialize(piIntegrationContact);
        encryptedAPIList = piIntegration.PIFields;
        sobjectPrefix = piIntegration.sobjectPrefix;
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response saveRepair(String repairJson,String transId,Boolean isNew) {
        System.debug('Repair__c Info:' + JSON.serialize(repairJson));
        //1. Prepare the payload for  Repair__c
        Schema.SObjectType repairSchema = schemaMap.get(sobjectTypeValue);
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = repairSchema.getDescribe().fields.getMap();
        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(repairJson);
        Repair__c repairInfo = new Repair__c();
        //自定义格式转换
        for (String fieldAPI: fieldValueMap.keySet()) {
            system.debug('field API'+fieldAPI);
            Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType();
            String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI));
            if(String.isBlank(fieldValue)){
                continue;
            }
            if(String.valueOf(fielddataType)=='DATE'){
                repairInfo.put(fieldAPI, Date.valueOf(String.valueOf(fieldValueMap.get(fieldAPI)).replace('/', '-')));
            }else if(String.valueOf(fielddataType)=='DATETIME'){
                String dt = String.valueOf(fieldValueMap.get(fieldAPI));
                if(String.isNotBlank(dt)&&dt.contains('T')){
                    dt = dt.replace('T',' ');
                    repairInfo.put(fieldAPI, Datetime.valueOfGmt(dt));
                }
            }else if(String.valueOf(fielddataType)=='PERCENT'||String.valueOf(fielddataType)=='CURRENCY'||String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){
                repairInfo.put(fieldAPI, Decimal.valueOf(String.valueOf(fieldValueMap.get(fieldAPI))));
            } else if(String.valueof(fielddataType)=='BOOLEAN'){
                repairInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            }else {
                repairInfo.put(fieldAPI, String.valueOf(fieldValueMap.get(fieldAPI)));
            }
        }
        //2. Save Record Process
        String status = 'success';
        Response resp = new Response();
        Savepoint sp = Database.setSavepoint();
        String rid = '';
        try{
            System.debug('abcde');
            if(isNew){
                System.debug('repairInfozhj = ' + repairInfo);
                insert repairInfo;
            }else{
                System.debug('into update');
                String awsDataId = (String)repairInfo.get('AWS_Data_Id__c');
                System.debug('awsDataId = ' + awsDataId);
                Repair__c[] repairs = [select id from Repair__c where AWS_Data_Id__c =:awsDataId];
                System.debug('repairs[0].id = ' + repairs[0].id);
                repairInfo.put('Id',repairs[0].id);//For testing;
                update repairInfo;
            }
            rid=repairInfo.Id;
            PIHelper.saveTransLog(sobjectTypeValue,rid,transId, (String)repairInfo.get('AWS_Data_Id__c'),repairJson ,status,'');
            resp.recordId = repairInfo.Id;
            resp.message = '';
            resp.status = status;
            System.debug('resp from sfdx back-end' + resp);
            return resp;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            status = 'fail';
            PIHelper.saveTransLog(sobjectTypeValue,rid,transId, (String)repairInfo.get('AWS_Data_Id__c'),repairJson,status,e.getMessage());
            resp.message = e.getMessage();
            resp.status = status;
            return resp;
        }
    }
}
force-app/main/default/classes/NewRepairController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/OnCallController.cls
New file
@@ -0,0 +1,129 @@
global without sharing class OnCallController {
    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
    public String awsToken{set;get;}
    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    public static String sobjectTypeValue = 'On_Call__c';
    public Boolean isNewMode{set;get;}
    public String rtTypeId {get; set;}
    public String AWSDataId{set;get;}
    public List<String> encryptedAPIList{set;get;}
    public String staticResource {get; set;}
    public String staticResourceContact {get; set;}
    public String requiredFieldAPIListStr {get; set;}
    public String fieldAPIToLabelMapStr {get; set;}
    public String Input_Required_Field_Msg{set;get;}
    public String PIPL_Name_Label{set;get;}
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public String sobjectPrefix{set;get;}
    public String sobjecttypeForFrontEnd{set;get;}
    // public String sobjectId{set;get;}
    public OnCallController(ApexPages.StandardController controller) {
        // sobjectId = [SELECT CustomObjectId,CustomObjectName  FROM CustomObjectUserLicenseMetrics   where CustomObjectName ='OnCall' limit 1].CustomObjectId;
        isNewMode = true;
        Input_Required_Field_Msg = Label.Input_Required_Field_Msg;
        PIPL_Name_Label = Label.PIPL_Name_Label;
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        sobjecttypeForFrontEnd = sobjectTypeValue;
        //获取所有字段
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('On_Call__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        SObject obj = controller.getRecord();
        if(obj.Id != null){
            //更新
            isNewMode = false;
            On_Call__c onCallData = [select Id,AWS_Data_Id__c from On_Call__c where id =: obj.Id];
            AWSDataId = onCallData.AWS_Data_Id__c;
        }else{
            //新建
            rtTypeId = null;
        }
        LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, 'On_Call__c','classic');
        layoutSections = LayoutWrapperValue.layoutSections;
        List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
        Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
        requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
        fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
        PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo('On_Call__c');
        staticResource = JSON.serialize(piIntegration);
        encryptedAPIList = piIntegration.PIFields;
        sobjectPrefix = piIntegration.sobjectPrefix;
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response saveOnCall(String onCallJson,String transId,Boolean isNew) {
        System.debug('On_Call__c Info:' + JSON.serialize(onCallJson));
        //1. Prepare the payload for  On_Call__c
        Schema.SObjectType onCallSchema = schemaMap.get(sobjectTypeValue);
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = onCallSchema.getDescribe().fields.getMap();
        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(onCallJson);
        On_Call__c onCallInfo = new On_Call__c();
        //自定义格式转换
        for (String fieldAPI: fieldValueMap.keySet()) {
            system.debug('field API'+fieldAPI);
            Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType();
            String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI));
            if(String.isBlank(fieldValue)){
                continue;
            }
            if(String.valueOf(fielddataType)=='DATE'){
                onCallInfo.put(fieldAPI, Date.valueOf(String.valueOf(fieldValueMap.get(fieldAPI)).replace('/', '-')));
            }else if(String.valueOf(fielddataType)=='DATETIME'){
                String dt = String.valueOf(fieldValueMap.get(fieldAPI));
                if(String.isNotBlank(dt)&&dt.contains('T')){
                    dt = dt.replace('T',' ');
                    onCallInfo.put(fieldAPI, Datetime.valueOfGmt(dt));
                }
            }else if(String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){
                onCallInfo.put(fieldAPI, Decimal.valueOf(String.valueOf(fieldValueMap.get(fieldAPI))));
            } else if(String.valueof(fielddataType)=='BOOLEAN'){
                onCallInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            }else {
                onCallInfo.put(fieldAPI, String.valueOf(fieldValueMap.get(fieldAPI)));
            }
        }
        //2. Save Record Process
        String status = 'success';
        Response resp = new Response();
        Savepoint sp = Database.setSavepoint();
        String rid = '';
        try{
            System.debug('abcde');
            if(isNew){
                System.debug('onCallInfozhj = ' + onCallInfo);
                insert onCallInfo;
            }else{
                System.debug('into update');
                String awsDataId = (String)onCallInfo.get('AWS_Data_Id__c');
                System.debug('awsDataId = ' + awsDataId);
                On_Call__c[] onCalls = [select id from On_Call__c where AWS_Data_Id__c =:awsDataId];
                System.debug('onCalls[0].id = ' + onCalls[0].id);
                onCallInfo.put('Id',onCalls[0].id);//For testing;
                update onCallInfo;
            }
            rid=onCallInfo.Id;
            PIHelper.saveTransLog(sobjectTypeValue,rid,transId, (String)onCallInfo.get('AWS_Data_Id__c'),onCallJson ,status,'');
            resp.recordId = onCallInfo.Id;
            resp.message = '';
            resp.status = status;
            System.debug('resp from sfdx back-end' + resp);
            return resp;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            status = 'fail';
            PIHelper.saveTransLog(sobjectTypeValue,rid,transId, (String)onCallInfo.get('AWS_Data_Id__c'),onCallJson,status,e.getMessage());
            resp.message = e.getMessage();
            resp.status = status;
            return resp;
        }
    }
}
force-app/main/default/classes/OnCallController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/Option.cls
New file
@@ -0,0 +1,5 @@
public class Option {
    @AuraEnabled public string label{get;set;}
    @AuraEnabled public string value{get;set;}
    @AuraEnabled public boolean Selected{get;set;}
}
force-app/main/default/classes/Option.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/PIHelper.cls
New file
@@ -0,0 +1,216 @@
/*
 * Author: Bubba Li
 * Created Date: 01/26/2022
 * Purpose: Utility class for PI
 * Test Class: PIHelper
 * History:
 *      01/26/2022 - Bubba Li - Initial Code.
 *
 * */
global without sharing class PIHelper {
    public static String getObjectKeyPrefix(String objName){
        try{
            schema.sObjectType sObjType = Schema.getGlobalDescribe().get(objName);
            return (sObjType.getDescribe().getKeyPrefix());
        }catch(Exception e){
            system.debug('Exception from get key prefix:'+e.getMessage());
            return '';
        }
    }
    // confirm file transaction
    @future(callout =true)
    public static void confirmFileTrans(String module,Integer isSuccess, String   sfRecordId ,String transId ,String token,String transUrl){
        Boolean result =false;
        Transaction_Log__c traLog = new Transaction_Log__c();
        traLog.Module__c = 'ConfirmFileTransaction '+module;
        traLog.Interface_URL__c = transUrl;
        traLog.TransId__c = transId;
        traLog.SFRecordId__c=sfRecordId;
        try {
            Http http = new Http();
            HttpRequest request = new HttpRequest();
            request.setEndpoint(transUrl);
            request.setMethod('POST');
            TransRequestBody requestBody =new TransRequestBody();
            requestBody.isSuccess=isSuccess;
            requestBody.sfRecordId=sfRecordId;
            requestBody.txId =transId;
            request.setBody(JSON.serialize(requestBody));
            system.debug('request---'+request.tostring());
            HttpResponse response = http.send(request);
            system.debug('token--'+token);
            system.debug('confirm result--'+response.getBody());
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
            result = (Boolean)results.get('success');
            System.debug('result = ' + result);
            traLog.Status__c = 'success';
            traLog.Response__c=response.getBody();
        } catch (Exception e) {
            traLog.Status__c = 'fail';
            traLog.Response__c = e.getMessage();
        }
        insert traLog;
    }
     // confirm tx transaction
     public static void confirmTrans(String module,Integer isSuccess, String   sfRecordId ,String transId ,String token,String transUrl,List<idList> idList){
         Boolean result =false;
         Transaction_Log__c traLog = new Transaction_Log__c();
         traLog.Module__c = 'Confirm Transaction '+module;
         traLog.Interface_URL__c = transUrl;
         traLog.TransId__c = transId;
         if (!String.isEmpty(sfRecordId)) {
            traLog.SFRecordId__c=sfRecordId;
         }else {
            traLog.SFRecordId__c=JSON.serialize(idList);
         }
         try {
             Http http = new Http();
             HttpRequest request = new HttpRequest();
             request.setEndpoint(transUrl);
             request.setMethod('POST');
             TransactionRequestBody requestBody =new TransactionRequestBody();
             requestBody.isSuccess=isSuccess;
             requestBody.sfRecordId=sfRecordId;
             requestBody.idList=idList;
             requestBody.txId =transId;
             request.setBody(JSON.serialize(requestBody));
             system.debug('request---'+request.tostring());
             HttpResponse response = http.send(request);
             system.debug('confirm result--'+response.getBody());
             Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
             result = (Boolean)results.get('success');
             System.debug('result = ' + result);
             traLog.Status__c = 'success';
             traLog.Response__c=response.getBody();
         } catch (Exception e) {
             traLog.Status__c = 'fail';
             traLog.Response__c = e.getMessage();
         }
         insert traLog;
     }
    // Use this log method
    public static void saveTransLog(String module,String awsDataId,String sfId, String transId,String content,String status,String respMsg){
        Transaction_Log__c traLog = new Transaction_Log__c();
        traLog.AWS_Data_Id__c = awsDataId;
        traLog.SFRecordId__c = sfId;
        traLog.Module__c = 'Upsert SF ' + module;
        traLog.TransId__c = transId;
        traLog.Request__c = content;
        traLog.Status__c = status;
        traLog.Response__c = respMsg;
        traLog.Interface_URL__c = traLog.Module__c;
        insert traLog;
    }
    public static PIIntegration getPIIntegrationInfo(String sobjectType){
        PIIntegration piIntegration = new PIIntegration();
        //查询url
        PI_Policy_Configuration__c config = [select Full_New_URL__c,Full_Search_URL__c,Full_Update_URL__c,Full_Undelete_URL__c,Full_Read_URL__c,Full_Delete_URL__c,Full_View_Unified_Contact_URL__c,TransactionURL__c from PI_Policy_Configuration__c where Sobject_Type__c =: sobjectType];
        System.debug('config = ' + config);
        //获取appid和appsecret
        AWS_Integration_Info__mdt awsConfiguration = [SELECT App_Id__c,Token_URL__c,App_Secret__c,Host_URL__c FROM AWS_Integration_Info__mdt  WHERE DeveloperName = 'AWS_Default_Configuration'];
        if (awsConfiguration == null) {
            System.debug('AWS_Integration_Info__mdt没配置');
            return null;
        }
        String awsAppId = awsConfiguration.App_Id__c;
        String awsAppSecret = awsConfiguration.App_Secret__c;
        System.debug('awsAppId = ' + awsAppId);
        System.debug('awsAppSecret = ' + awsAppSecret);
        System.debug('Host_URL__c = ' + awsConfiguration.Host_URL__c);
        System.debug('Token URL = ' + awsConfiguration.Token_URL__c);
        //获取token
        String token = '';
        try{
            Http http = new Http();
            HttpRequest request = new HttpRequest();
            String url = awsConfiguration.Token_URL__c;
            request.setEndpoint(url);
            request.setMethod('GET');
            HttpResponse response = http.send(request);
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
            token = (String)results.get('object');
            System.debug('token = ' + token);
        }catch(Exception e){
            Transaction_Log__c traLog = new Transaction_Log__c();
            traLog.Module__c = 'Get Token';
            traLog.Status__c = 'fail';
            traLog.Response__c = e.getMessage();
            traLog.Interface_URL__c = awsConfiguration.Token_URL__c;
            insert traLog;
        }
        //Insert Get Token Log
        //获取敏感字段
        piIntegration.PIDetails = [select id,PI_Policy_Configuration__r.Full_New_URL__c, Enable_Encrypt__c, SF_Field_API_Name__c,SF_Field_Encrypted_API__c, AWS_Field_API__c,AWS_Encrypted_Field_API__c,Field_Type__c from PI_Field_Policy_Detail__c  where PI_Policy_Configuration_Name__c =:sobjectType and Enable_Encrypt__c=true];
        List<String> vLookUpFields = new List<String>();
        List<String> PIFields = new List<String>();
        for (PI_Field_Policy_Detail__c PIDetail : piIntegration.PIDetails) {
            if(PIDetail.Field_Type__c == 'Reference'){
                vLookUpFields.add(PIDetail.SF_Field_API_Name__c);
            }
            PIFields.add(PIDetail.SF_Field_API_Name__c);
        }
        System.debug('vLookUpFields = ' + vLookUpFields.toString());
        System.debug('PIFields = ' + PIFields.toString());
        //填充数据
        piIntegration.newUrl = config.Full_New_URL__c;
        piIntegration.updateUrl = config.Full_Update_URL__c;
        piIntegration.queryUrl = config.Full_Read_URL__c;
        piIntegration.deleteUrl = config.Full_Delete_URL__c;
        piIntegration.undeleteUrl = config.Full_Undelete_URL__c;
        piIntegration.viewUnifiedContactUrl = config.Full_View_Unified_Contact_URL__c;
        piIntegration.transactionURL = config.TransactionURL__c;
        piIntegration.hostUrl = awsConfiguration.Host_URL__c;
        piIntegration.searchUrl = config.Full_Search_URL__c;
        piIntegration.token = token;
        piIntegration.awsAppId = awsAppId;
        piIntegration.awsAppSecret = awsAppSecret;
        piIntegration.vLookUpFields = vLookUpFields;
        piIntegration.PIFields = PIFields;
        piIntegration.sobjectPrefix = getObjectKeyPrefix(sobjectType);
        System.debug('piIntegration' + piIntegration);
        return piIntegration;
    }
    global class PIIntegration{
        public String sobjectPrefix{set;get;}
        public String searchUrl{set;get;}
        public String newUrl{set;get;}
        public String updateUrl{set;get;}
        public String queryUrl{set;get;}
        public String deleteUrl{set;get;}
        public String undeleteUrl{set;get;}
        public String viewUnifiedContactUrl{set;get;}
        public String hostUrl{set;get;}
        public String token{set;get;}
        public String awsAppId{set;get;}
        public String awsAppSecret{set;get;}
        public String transactionUrl{set;get;}
        public List<String> vLookUpFields{set;get;}
        public List<String> PIFields{set;get;}
        public List<PI_Field_Policy_Detail__c > PIDetails{set;get;}
    }
    global class TransRequestBody{
        public Integer isSuccess{set;get;}
        public String sfRecordId{set;get;}
        public String txId{set;get;}
    }
    global class TransactionRequestBody{
        public Integer isSuccess{set;get;}
        public String sfRecordId{set;get;}
        public String txId{set;get;}
        public List<idList> idList{set;get;}
    }
    global class idList{
        public String awsId{set;get;}
        public String sfRecordId{set;get;}
    }
}
force-app/main/default/classes/PIHelper.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/RentalApplyController.cls
New file
@@ -0,0 +1,153 @@
global without sharing class RentalApplyController {
    public List <LayoutDescriberHelper.LayoutSection > layoutSections{set;get;}
    public String awsToken{set;get;}
    public static Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
    public static String sobjectTypeValue = 'Rental_Apply__c';
    public Boolean isNewMode{set;get;}
    public String rtTypeId {get; set;}
    public String AWSDataId{set;get;}
    public List<String> encryptedAPIList{set;get;}
    public String staticResource {get; set;}
    public String staticResourceContact {get; set;}
    public String requiredFieldAPIListStr {get; set;}
    public String fieldAPIToLabelMapStr {get; set;}
    public String Input_Required_Field_Msg{set;get;}
    public String requiredErrorMsg{set;get;}
    public String contactsInfo {set;get;}
    public String contactId{set;get;}
    public String PIPL_Input_Account_Error_Msg{set;get;}
    public RentalApplyController(ApexPages.StandardController controller) {
        isNewMode = true;
        Input_Required_Field_Msg = Label.Input_Required_Field_Msg;
        PIPL_Input_Account_Error_Msg = label.PIPL_Input_Account_Error_Msg;
        //获取所有字段
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Rental_Apply__c').getDescribe().fields.getMap().keyset());
        controller.addFields(fieldList);
        SObject obj = controller.getRecord();
        if(obj.Id != null){
            //更新
            isNewMode = false;
            Rental_Apply__c rentalApplyData = [select Id,RecordTypeId,AWS_Data_Id__c,Loaner_medical_Staff__c,Loaner_medical_Staff__r.AWS_Data_Id__c from Rental_Apply__c where id =: obj.Id];
            rtTypeId = rentalApplyData.RecordTypeId;
            AWSDataId = rentalApplyData.AWS_Data_Id__c;
            Map<String,String> sfIdToAWSIdMap = new Map<String,String>();
            sfIdToAWSIdMap.put(String.valueof(rentalApplyData.Loaner_medical_Staff__r.Id).subString(0,15),rentalApplyData.Loaner_medical_Staff__r.AWS_Data_Id__c);
            contactsInfo = JSON.serialize(sfIdToAWSIdMap);
        }else{
            //新建
            rtTypeId = ApexPages.currentPage().getParameters().get('RecordType');
        }
        LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, 'Rental_Apply__c','classic');
        layoutSections = LayoutWrapperValue.layoutSections;
        List<String> requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList;
        Map<String,String> fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap;
        requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList);
        fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap);
        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Rental_Apply__c'));
        encryptedAPIList = PIHelper.getPIIntegrationInfo('Rental_Apply__c').PIFields;
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
    }
    global class Response{
        public String recordId{set;get;}
        public String message{set;get;}
        public String status{set;get;}
    }
    @RemoteAction
    global static Response saveRentalApply(String rentalApplyJson,String transId,Boolean isNew) {
        System.debug('Rental_Apply__c Info:' + JSON.serialize(rentalApplyJson));
        //1. Prepare the payload for  Rental_Apply__c
        Schema.SObjectType rentalApplySchema = schemaMap.get(sobjectTypeValue);
        Map<String, Schema.SObjectField> fieldAPIToTypeMap = rentalApplySchema.getDescribe().fields.getMap();
        system.debug(fieldAPIToTypeMap);
        Map<String,Object> fieldValueMap = (Map<String,Object>)JSON.deserializeUntyped(rentalApplyJson);
        Rental_Apply__c rentalApplyInfo = new Rental_Apply__c();
        //自定义格式转换
        for (String fieldAPI: fieldValueMap.keySet()) {
            system.debug('field API='+fieldAPI);
            Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType();
            String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI));
            system.debug('Field Type:'+fielddataType+' field Value='+fieldValue);
            if(String.valueOf(fielddataType)=='DATE'){
                rentalApplyInfo.put(fieldAPI,(String.isBlank(fieldValue)||String.isEmpty(fieldValue))? null:Date.valueOf(fieldValue.replace('/', '-')));
            }else if(String.valueOf(fielddataType)=='DATETIME'){
                if(String.isNotBlank(fieldValue)&&fieldValue.contains('T')){
                    fieldValue = fieldValue.replace('T',' ');
                    rentalApplyInfo.put(fieldAPI, Datetime.valueOfGmt(fieldValue));
                }else{
                    rentalApplyInfo.put(fieldAPI, null);
                }
            }else if(String.valueof(fielddataType)=='CURRENCY'|| String.valueof(fielddataType)=='PERCENT'||String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){
                rentalApplyInfo.put(fieldAPI, (String.isBlank(fieldValue)||String.isEmpty(fieldValue))?0:Decimal.valueOf(fieldValue));
            } else if(String.valueof(fielddataType)=='BOOLEAN'){
                rentalApplyInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            }else {
                rentalApplyInfo.put(fieldAPI,fieldValue);
            }
            // system.debug('field API'+fieldAPI);
            // String fieldValue = String.valueOf(fieldAPIToTypeMap.get(fieldAPI));
            // if(String.isBlank(fieldValue) || String.isEmpty(fieldValue)){
            //     continue;
            // }
            // Schema.DescribeFieldResult fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe();
            // Schema.DisplayType fieldDatas = fielddataType.getType();
            // system.debug('fieldValue='+fieldValue);
            // if(String.valueOf(fielddatas)=='DATE'){
            //     rentalApplyInfo.put(fieldAPI, Date.valueOf(String.valueOf(fieldValueMap.get(fieldAPI)).replace('/', '-')));
            // }else if(String.valueOf(fielddatas)=='DATETIME'){
            //     String dt = String.valueOf(fieldValueMap.get(fieldAPI));
            //     if(String.isNotBlank(dt)&&dt.contains('T')){
            //         dt = dt.replace('T',' ');
            //         rentalApplyInfo.put(fieldAPI, Datetime.valueOfGmt(dt));
            //     }
            // }else if(String.valueOf(fielddatas)=='Number'||String.valueOf(fielddatas)=='DOUBLE'){
            //     system.debug('decimal error:'+ String.valueOf(fieldValueMap.get(fieldAPI)));
            //     rentalApplyInfo.put(fieldAPI, decimal.valueOf(String.valueOf(fieldValueMap.get(fieldAPI))));
            // } else if(String.valueof(fielddatas)=='BOOLEAN'){
            //     rentalApplyInfo.put(fieldAPI, fieldValueMap.get(fieldAPI));
            // }else {
            //     rentalApplyInfo.put(fieldAPI, String.valueOf(fieldValueMap.get(fieldAPI)));
            // }
        }
        //2. Save Record Process
        String status = 'success';
        Response resp = new Response();
        Savepoint sp = Database.setSavepoint();
        String rid = '';
        try{
            System.debug('abcde');
            if(isNew){
                System.debug('rentalApplyInfozhj = ' + rentalApplyInfo);
                insert rentalApplyInfo;
                System.debug('rentalApplyInfo.Id' + rentalApplyInfo.Id);
            }else{
                System.debug('into update');
                String awsDataId = (String)rentalApplyInfo.get('AWS_Data_Id__c');
                System.debug('awsDataId = ' + awsDataId);
                Rental_Apply__c[] RentalApplys = [select id from Rental_Apply__c where AWS_Data_Id__c =:awsDataId];
                System.debug('RentalApplys[0].id = ' + RentalApplys[0].id);
                rentalApplyInfo.put('Id',RentalApplys[0].id);//For testing;
                update rentalApplyInfo;
            }
            rid=rentalApplyInfo.Id;
            // PIHelper.saveTransLog(sobjectTypeValue,transId, (String)rentalApplyInfo.get('AWS_Data_Id__c'),rentalApplyJson ,status,'');
            PIHelper.saveTransLog(sobjectTypeValue,(String)rentalApplyInfo.get('AWS_Data_Id__c'),rid,transId,rentalApplyJson,status,'');
            resp.recordId = rid;
            resp.message = 'success saveRentalApply';
            resp.status = status;
            System.debug('respzhj = ' + resp);
            return resp;
        } catch(Exception e) {
            System.debug('into catch'+e.getMessage());
            Database.rollback(sp);
            status = 'fail';
            // PIHelper.saveTransLog(sobjectTypeValue,transId, (String)rentalApplyInfo.get('AWS_Data_Id__c'),rentalApplyJson,status,e.getMessage());
            PIHelper.saveTransLog(sobjectTypeValue,(String)rentalApplyInfo.get('AWS_Data_Id__c'),rid,transId,rentalApplyJson,status,e.getMessage());
            resp.message = e.getMessage();
            resp.status = status;
            return resp;
        }
    }
}
force-app/main/default/classes/RentalApplyController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/SObjectHelper.cls
New file
@@ -0,0 +1,445 @@
public without sharing class SObjectHelper {
    /**
     * Copy every field values from from_sobj to to_sobj, if the field is in to_sobj and the value is not null
     */
    public static void MergeValue(Sobject to_sobj,Sobject from_sobj)
    {
        CopyTo(to_sobj,from_sobj,true);
    }
    /**
     * Copy every field values from from_sobj to to_sobj
     */
    public static void OverwriteValue(Sobject to_sobj,Sobject from_sobj)
    {
        CopyTo(to_sobj,from_sobj,false);
    }
    static void CopyTo(Sobject to_sobj,Sobject from_sobj, Boolean skip_from_null)
    {
        Map<String, Schema.SObjectField> to_sobj_map = GetFields(to_sobj.getSObjectType().getDescribe().getName());
        Map<String, Schema.SObjectField> from_sobj_map = GetFields(from_sobj.getSObjectType().getDescribe().getName());
        for (string field : from_sobj_map.keySet()) {
            object obj = from_sobj.get(field);
            object obj1 = to_sobj.get(field);
            if (obj != obj1 && to_sobj_map.containsKey(field) && to_sobj_map.get(field).getDescribe().isUpdateable()) {
                if (obj != null || !skip_from_null) {
                    System.debug('obj='+obj);
                    System.debug('obj1='+obj1);
                    to_sobj.put(field, obj);
                }
            }
        }
    }
    private static Map<string,Map<String, Schema.SObjectField>> sobject_field_map = new Map<string,Map<String, Schema.SObjectField>>();
    public static Map<String, Schema.SObjectField> GetFieldMap(string obj_name)
    {
        Map<String, Schema.SObjectField> fm = null;
        if(string.isBlank(obj_name))return fm;
        if(sobject_field_map.containsKey(obj_name))
        {
            fm = sobject_field_map.get(obj_name);
        }
        else
        {
            fm = GetFields(obj_name);
            if (fm != null) {
                sobject_field_map.put(obj_name, fm);
            }
        }
        return fm;
    }
/*
    private static Map<string,Set<string>> sobject_common_fields = new Map<string,Set<string>>();
    // get sobject fields that not be assigned in FieldPermission, they were stardard fields
    public static Set<string> GetCommonFields(string obj_name)
    {
        Set<string> fields = null;
        if(string.isBlank(obj_name))return fields;
        if(sobject_common_fields.containsKey(obj_name))
        {
            fields = sobject_common_fields.get(obj_name);
        }
        else
        {
            Map<String, Schema.SObjectField> all_fields = GetFieldMap(obj_name);
            Id profile_id = UserUtility.GetSysAdminProfileId();
            List<FieldPermissions> lfp = [SELECT Id, ParentId, SobjectType, Field, PermissionsEdit, PermissionsRead, SystemModstamp FROM FieldPermissions
            where parentId in (select id from permissionset where PermissionSet.Profile.Id = :profile_id) and sobjecttype = :obj_name ];
            Set<string> admin_s = new Set<string>();
            for(FieldPermissions fp : lfp)
            {
                if(fp.PermissionsRead)
                {
                    admin_s.add(fp.Field.replace(fp.SobjectType+'.',''));
                }
            }
            // if a field not in admin's permission, the field is a common(standard) field
            for (string f : all_fields.keySet()) {
                if (!admin_s.contains(f) && !f.endsWith('__c')) {
                    if (fields == null) {
                        fields = new Set<string>();
                    }
                    fields.add(f);
                }
            }
            if (fields != null) {
                sobject_common_fields.put(obj_name, fields);
            }
        }
        return fields;
    }
    public static Set<string> GetCurrentProfileAccessableFields(string obj_name)
    {
        return GetProfileAccessableFields(UserInfo.getProfileId(), obj_name);
    }
    private static Map<Id,Map<string,List<FieldPermissions>>> profile_field_permission_buffer = new Map<Id,Map<string,List<FieldPermissions>>>();
    public static Set<string> GetProfileAccessableFields(Id profile_id, string obj_name)
    {
        List<FieldPermissions> lfp = null;
        if(!profile_field_permission_buffer.containsKey(profile_id) || !profile_field_permission_buffer.get(profile_id).containsKey(obj_name)){
            lfp = [SELECT Id, ParentId, SobjectType, Field, PermissionsEdit, PermissionsRead, SystemModstamp FROM FieldPermissions
                                        where parentId in (select id from permissionset where PermissionSet.Profile.Id = :profile_id) and sobjecttype = :obj_name ];
            system.debug(string.format('profile {0} object {1} updated ', new object[]{profile_id,obj_name,lfp.size()}));
            Map<string,List<FieldPermissions>> temp = null;
            if(profile_field_permission_buffer.containsKey(profile_id))
            {
                temp = profile_field_permission_buffer.get(profile_id);
            }
            else{
                temp = new Map<string,List<FieldPermissions>>();
                profile_field_permission_buffer.put(profile_id,temp);
            }
            temp.put(obj_name,lfp);
        }
        else{
            lfp = profile_field_permission_buffer.get(profile_id).get(obj_name);
        }
        Set<string> ls = new Set<string>();
        for(FieldPermissions fp : lfp)
        {
            if(fp.PermissionsRead)
            {
                ls.add(fp.Field.replace(fp.SobjectType+'.',''));
            }
        }
        Set<string> css = GetCommonFields(obj_name);
        if (css != null) {
            ls.addAll(css);
        }
        return ls;
    }*/
    public static Map<string,FieldInfo> GetFieldInfos(string obj_name)
    {
        Map<string,Schema.SObjectField> fields_map = SObjecthelper.GetFieldMap(obj_name);
        if(fields_map == null)
        {
            return null;
        }
        Map<string,FieldInfo> res = new Map<string,FieldInfo>();
        Map<string,FieldInfo> result = new Map<string,FieldInfo>();
        FieldInfo temp = null;
        for(string s : fields_map.keySet())
        {
            Schema.DescribeFieldResult dfr = fields_map.get(s).getDescribe();
            temp = new FieldInfo();
            temp.Name = dfr.getName();
            temp.Label = dfr.getLabel();
            // resolve 'Business Phone' bug
            if(obj_name.toLowerCase() == 'contact' && temp.Name =='Phone' && temp.Label =='Business Phone'){
                temp.Label = 'Phone';
            }
            Schema.DisplayType dt = dfr.getType();
            temp.TypeEnumName = dt.name();
            //temp.DisplayType = dt;
            if((dt == schema.DisplayType.MULTIPICKLIST) || (dt == schema.DisplayType.PICKLIST) )
            {
                temp.Options = new List<Option>();
                List<Schema.PicklistEntry> pick_list_values = dfr.getPickListValues();
                for (Schema.PicklistEntry a : pick_list_values) {
                    if (!a.isActive()) {
                        continue;
                    }
                    Option lv = new Option();
                    lv.label = a.getLabel();
                    lv.value = a.getValue();
                    temp.Options.add(lv);
                }
            }
            if(dt == schema.DisplayType.REFERENCE )
            {
                temp.References = new List<Option>();
                for(Schema.SObjectType reference : dfr.getReferenceTo()) {
                    System.debug('Lookup reference object name: ' + reference.getDescribe().getName());
                    System.debug('Lookup reference object label: ' + reference.getDescribe().getLabel());
                    Option lv = new Option();
                    lv.label = reference.getDescribe().getLabel();
                    lv.value = reference.getDescribe().getName();
                    temp.References.add(lv);
                }
                List<Schema.PicklistEntry> pick_list_values = dfr.getPickListValues();
                for (Schema.PicklistEntry a : pick_list_values) {
                    if (!a.isActive()) {
                        continue;
                    }
                }
            }
            res.put(s,temp);
        }
        return res;
    }
    public static Map<String, Schema.SObjectField> GetFields(Sobject sobj ){
        return GetFields(sobj.getSObjectType().getDescribe().getName());
    }
    public static Map<String, Schema.SObjectField> GetFields(string obj_name )
    {
        Map<String, Schema.SObjectType> mss = Schema.getGlobalDescribe();
        if(mss.containsKey(obj_name)){
            return Transform(mss.get(obj_name).getDescribe().fields.getMap());
        }
        else{
            return null;
        }
    }
    public static Map<String, Schema.FieldSet> GetFieldSets(string obj_name )
    {
        Map<String, Schema.SObjectType> mss = Schema.getGlobalDescribe();
        if(!mss.containsKey(obj_name))return null;
        Map<String, Schema.FieldSet> mssfs = mss.get(obj_name).getDescribe().fieldSets.getMap();
        return mssfs;
    }
    public static Map<String, Schema.FieldSetMember> GetFieldSet(string obj_name,string field_set_name )
    {
        Map<String, Schema.FieldSet> mssfs = GetFieldSets(obj_name);
        if(!mssfs.containsKey(field_set_name))return null;
        Map<String, Schema.FieldSetMember> result = new Map<String, Schema.FieldSetMember>();
        for(Schema.FieldSetMember member : mssfs.get(field_set_name).getFields()){
            Schema.SObjectField ssf = member.getSObjectField();
            result.put(ssf.getDescribe().getName(),member);
        }
        return result;
    }
    static Map<String, Schema.SObjectField> Transform(Map<String, Schema.SObjectField> mssof){
        if(mssof == null)return null;
        Map<String, Schema.SObjectField> result = new Map<String, Schema.SObjectField>();
        for(string key : mssof.keySet()){
            result.put(mssof.get(key).getDescribe().getName(),mssof.get(key));
        }
        return result;
    }
    /*
    static Map<String, Schema.FieldSet> Transform(Map<String, Schema.FieldSet> mssfs){
        if(mssfs == null)return null;
        Map<String, Schema.FieldSet> result = new Map<String, Schema.FieldSet>();
        for(string key : mssfs.keySet()){
            result.put(mssfs.get(key).getName(),mssfs.get(key));
        }
        return result;
    }*/
    public static Map<string,string> GetPicklistLabelValueMap(string objectName, string fieldName){
        List<Schema.PicklistEntry> temp = GetPicklistEntryList(objectName,fieldName);
        if(temp == null)return null;
        Map<string,string> res = new Map<string,string>();
        for(Schema.PicklistEntry pe : temp){
            res.put(pe.getLabel(),pe.getValue());
        }
        return res;
    }
    public static Map<string,string> GetPicklistValueLabelMap(string objectName, string fieldName){
        List<Schema.PicklistEntry> temp = GetPicklistEntryList(objectName,fieldName);
        if(temp == null)return null;
        Map<string,string> res = new Map<string,string>();
        for(Schema.PicklistEntry pe : temp){
            res.put(pe.getValue(),pe.getLabel());
        }
        return res;
    }
    public static List<Schema.PicklistEntry> GetPicklistEntryList(string objectName, string fieldName){
        Map<String,String> picklistMap = new Map<String,String>();
        Schema.SObjectType targetSobjectType = Schema.getGlobalDescribe().get(objectName);
        Schema.DescribeSObjectResult objectDescribe = targetSobjectType.getDescribe();
        Map<String, Schema.SObjectField> fieldMap = objectDescribe.fields.getMap();
        if(!fieldMap.containsKey(fieldName))return null;
        List<Schema.PicklistEntry> picklistEntries = fieldMap.get(fieldName).getDescribe().getPickListValues();
        return picklistEntries;
    }
    public static string GetFieldDescription(string object_name, string field_name){
        if(string.isBlank(object_name) || String.isBlank(field_name))return null;
        // List<FieldDefinition> fd = [Select Label, QualifiedApiName, Description from FieldDefinition Where EntityDefinition.QualifiedApiName=:object_name and QualifiedApiName=:field_name];
        List<FieldDefinition> fds = GetFieldDefinitions(object_name);
        for(FieldDefinition fd : fds)
        {
            if(fd.QualifiedApiName == field_name){
                return fd.Description;
            }
        }
        return null;
    }
    public static List<FieldDefinition> GetFieldDefinitions(string object_name){
        return [Select Label, QualifiedApiName, Description from FieldDefinition Where EntityDefinition.QualifiedApiName=:object_name];
    }
    /*
    public static Schema.FieldSet GetFieldSet(string obj_name,string fieldset_name )
    {
        Map<String, Schema.FieldSet> msf = GetFieldSets(obj_name);
        if(msf.containsKey(fieldset_name))return msf.get(fieldset_name);
        return null;
    }
    public static Schema.FieldSet GetFieldSetByName(string obj_name,string fieldset_name )
    {
        Map<String, Schema.FieldSet> msf = GetFieldSets(obj_name);
        for(string key : msf.keyset())
        {
            if(msf.get(key).getName() == fieldset_name )
            {
                return msf.get(key);
            }
        }
        return null;
    }*/
    /**
     * get sobject field value, support forign field if it was queried
     * e.g. GetSObjectField(lead_obj,'Owner.Name')
     */
    public static object GetSObjectField(object o,string f_str){
        return GetSObjectField((sobject)o,f_str);
    }
    /**
     * get sobject field value, support forign field if it was queried
     * e.g. GetSObjectField(lead_obj,'Owner.Name')
     */
    public static object GetSObjectField(sobject o,string f_str){
        List<string> fields = f_str.split('\\.');
        //system.debug('fields = ' + fields);
        sobject temp = o;
        Object result = null;
        for(integer i =0; i < fields.size();i++){
            if(temp == null) return null;
            if(i==fields.size()-1){
                result = temp.get(fields[i]);
            }
            else{
                temp = temp.getSObject(fields[i]);
            }
            /*
            if(result instanceof SObject){
                temp = (SObject)result;
                continue;
            }
            break;*/
        }
        return result;
    }
    /*
    public static Schema.FieldSet GetFieldSetByLabel(string obj_name,string fieldset_lable )
    {
        Map<String, Schema.FieldSet> msf = GetFieldSets(obj_name);
        for(string key : msf.keyset())
        {
            if(msf.get(key).getLabel() == fieldset_lable )
            {
                return msf.get(key);
            }
        }
        return null;
    }*/
    public static List<string> GetMultiPickListOptions(string val){
        return GetOptions(val);
    }
    public static List<string> GetOptions(string val){
        if(val == null)return new List<string>();
            return ValidMultiPickListValue(val).split(';');
    }
    public static string AppendValueToMultiPickList(string old_val,string val){
        return ValidMultiPickListValue(old_val+';'+val);
    }
    public static string ValidMultiPickListValue( string val ){
        if(string.isBlank(val))return val;
        return ValidMultiPickListValue(val.split(';'));
    }
    public static string ValidMultiPickListValue( List<string> vals ){
        if(vals == null ) vals = new List<string>();
        Set<string> ss = new Set<string>(vals);
        List<string> ls = new List<string>();
        for(string s : ss){
            if(string.isBlank(s)){
                continue;
            }
            ls.add(s);
        }
        return string.join(ls, ';');
    }
}
force-app/main/default/classes/SObjectHelper.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/SearchContactController.cls
New file
@@ -0,0 +1,61 @@
/*
 * Author: Bubba Li
 * Created Date: 02/08/2022
 * Purpose: SearchContactController
 * Test Class: SearchContactController
 * History:
 *      02/08/2022 - Bubba Li - Initial Code.
 *
 * */
public without sharing class SearchContactController {
    public String searchKeyWord{set;get;}
    public String staticResource {get; set;}
    public String contactAWSIds {set;get;}
    public String contactsInfo {set;get;}
    public String PIPL_Search_Contact_Label{set;get;}
    public SearchContactController() {
        String accountId = ApexPages.currentPage().getParameters().get('accountId');
        PIPL_Search_Contact_Label = Label.PIPL_Search_Contact_Label;
        //1. Query Contact by accountId
        List<Contact> conList = new List<Contact>();
        system.debug('Account Id from Front-end:'+accountId);
        if(String.isNotBlank(accountId) && String.isNotEmpty(accountId)){
            conList = new List<Contact>([select Id,AWS_Data_Id__c from Contact where AccountId=:accountId and AWS_Data_Id__c!='']);
        }
        //2. Prepare the Contact Info
        Map<String,Contact> awsIdToContactMap = new Map<String,Contact>();
        List<String> conAWSIds = new List<String>();
        for(Contact con:conList){
            conAWSIds.add(con.AWS_Data_Id__c);
            awsIdToContactMap.put(con.AWS_Data_Id__c,con);
        }
        contactsInfo = JSON.serialize(awsIdToContactMap);
        contactAWSIds = JSON.serialize(conAWSIds);
        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
    }
    @RemoteAction
    public static Response searchContacts(String awsContactIds) {
        Response resp = new Response();
        resp.status = 'fail';
        if(String.isBlank(awsContactIds)||String.isEmpty(awsContactIds)){
            return resp;
        }
        List<String> awsDataIds = (List<String>) JSON.deserialize(awsContactIds, List<String>.class);
        Map<String,Contact> awsIdToContactMapTemp = new Map<String,Contact>();
        List<Contact> conListTemp = new List<Contact>([select Id,AWS_Data_Id__c from Contact where AWS_Data_Id__c in:awsDataIds]);
        for(Contact con:conListTemp){
            awsIdToContactMapTemp.put(con.AWS_Data_Id__c,con);
        }
        if(awsIdToContactMapTemp.keySet().size()>0){
            resp.status = 'success';
            resp.message = JSON.serialize(awsIdToContactMapTemp);
        }
        return resp;
    }
    public class Response{
        public String message{set;get;}
        public String status{set;get;}
    }
}
force-app/main/default/classes/SearchContactController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/SearchLeadController.cls
New file
@@ -0,0 +1,53 @@
public without sharing class SearchLeadController {
    public String searchKeyWord{set;get;}
    public String staticResource {get; set;}
    public String leadAWSIds {set;get;}
    public String leadsInfo {set;get;}
    public String PIPL_Search_Contact_Label{set;get;}
    public SearchLeadController() {
        // String accountId = ApexPages.currentPage().getParameters().get('accountId');
        PIPL_Search_Contact_Label = Label.PIPL_Search_Contact_Label;
        //1. Query Contact by accountId
        List<Lead> leadList = new List<Lead>();
        // system.debug('Account Id from Front-end:'+accountId);
        // if(String.isNotBlank(accountId) && String.isNotEmpty(accountId)){
        //     leadList = new List<Lead>([select Id,AWS_Data_Id__c from Lead where AccountId=:accountId and AWS_Data_Id__c!='']);
        // }
        leadList = new List<Lead>([select Id,AWS_Data_Id__c from Lead where AWS_Data_Id__c!='']);
        //2. Prepare the Contact Info
        Map<String,Lead> awsIdToLeadMap = new Map<String,Lead>();
        List<String> leAWSIds = new List<String>();
        for(Lead le:leadList){
            leAWSIds.add(le.AWS_Data_Id__c);
            awsIdToLeadMap.put(le.AWS_Data_Id__c,le);
        }
        leadsInfo = JSON.serialize(awsIdToLeadMap);
        leadAWSIds = JSON.serialize(leAWSIds);
        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Lead'));
    }
    @RemoteAction
    public static Response searchLeads(String awsLeadIds) {
        Response resp = new Response();
        resp.status = 'fail';
        if(String.isBlank(awsLeadIds)||String.isEmpty(awsLeadIds)){
            return resp;
        }
        List<String> awsDataIds = (List<String>) JSON.deserialize(awsLeadIds, List<String>.class);
        Map<String,Lead> awsIdToLeadMapTemp = new Map<String,Lead>();
        List<Lead> leadListTemp = new List<Lead>([select Id,AWS_Data_Id__c from Lead where AWS_Data_Id__c in:awsDataIds]);
        for(Lead le:leadListTemp){
            awsIdToLeadMapTemp.put(le.AWS_Data_Id__c,le);
        }
        if(awsIdToLeadMapTemp.keySet().size()>0){
            resp.status = 'success';
            resp.message = JSON.serialize(awsIdToLeadMapTemp);
        }
        return resp;
    }
    public class Response{
        public String message{set;get;}
        public String status{set;get;}
    }
}
force-app/main/default/classes/SearchLeadController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/SoqlHelper.cls
New file
@@ -0,0 +1,136 @@
public  class SoqlHelper {
    public static string DistinctQueryFields(string sql)
    {
        string query_fields = sql;
        if (query_fields == null) {
            return null;
        }
        query_fields = query_fields.trim();
        Integer sel_i = query_fields.indexOfIgnoreCase('select ');
        string sel = 'select ';
        if ( sel_i < 0) {
            sel = '';
        }
        string whe = '';
        Integer whe_i = query_fields.indexOfIgnoreCase(' from ');
        if ( whe_i >= 0) {
            whe = query_fields.substring(whe_i);
        }
        string query = query_fields.substring(sel_i < 0 ? 0 : sel.length(), whe_i < 0 ? query_fields.length() : whe_i);
        Set<string> ss = new Set<string>();
        for(string f : query.split(',')){
            string s = f.trim().toLowerCase();
            //System.debug('s='+s);
            ss.add(s);
        }
        return sel + QueryFields(ss) + whe;
    }
    public static string WId(string wid){
        return '\'' + wid + '\'';
    }
    public static string QueryFields(Set<string> lo){
        return QueryFields(new List<string>(lo));
    }
    public static string QueryFields(List<object> lo){
        return string.join(lo, ',');
    }
    public static string ToInCondition(List<AggregateResult> lar ,string key)
    {
        if(lar==null || lar.size() == 0)
        {
            return null;
        }
        string ss = ' ( ';
        boolean b = true;
        for(AggregateResult ar : lar)
        {
            if(ar.get(key)==null)continue;
            if( b )
            {
                b = false;
                ss += '\''+ar.get(key)+'\'';
            }
            else
            {
                ss += ',\''+ar.get(key)+'\'';
            }
        }
        ss+=') ';
        return ss;
    }
    public static string ToInCondition(Set<string> so){
        return ToInCondition(new List<string>(so));
    }
    public static string ToInCondition(List<object> lo)
    {
        Set<object> so = new Set<object>(lo);
        lo = new List<object>(so);
        return '(\''+ string.join(lo, '\',\'')+'\')';
    }
    public static void InsertList(List<Sobject> so_list)
    {
        if(so_list == null || so_list.size() == 0)return;
        insert so_list;
    }
    public static void UpdateList(List<Sobject> so_list)
    {
        if(so_list == null || so_list.size() == 0)return;
        update so_list;
    }
    public static Map<string,Database.UpsertResult> UpsertList(List<Sobject> so_list, Schema.SObjectField field)
    {
        Map<string,Database.UpsertResult> mid = new Map<string,Database.UpsertResult>();
        if(so_list == null || so_list.size() == 0)return mid;
        List<Database.UpsertResult> urList2 = Database.upsert( so_list, field, false);
        Set<String> accBasicRecordIdSet = new Set<String>();
        integer index = 0;
        string errorString = '';
        string field_str = field.getDescribe().getName();
        for(Database.UpsertResult ur : urList2){
            if(!ur.IsSuccess()){
                object fv = so_list[index].get(field_str);
                mid.put(fv+'',ur);
                errorString = '';
                for(Database.Error errs: ur.getErrors()){
                    errorString += errs.getMessage() + ';';
                }
                //LogHelper.CreateRunTimeLog('runtime error', errorString, false, fv+'');
            }
            index++;
        }
        return mid;
    }
    public static void DeleteList(List<Sobject> so_list)
    {
        if(so_list == null || so_list.size() == 0)return;
        delete so_list;
    }
    @future
    public static void DeleteListAsync(List<Id> id_list)
    {
        if(id_list == null || id_list.size() == 0)return;
        Database.delete(id_list);
    }
}
force-app/main/default/classes/SoqlHelper.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/TestClass.cls
New file
@@ -0,0 +1,41 @@
public without sharing class TestClass
{
    public static List<Metadata.LayoutSection> GetLayoutSections(string object_name, string layout_name){
        List<String> componentNameList = new List<String>{object_name+'-'+layout_name};
        //通过Metadata.Operations.retrieve获取metadata
        //Metadata.Layout -> Metadata.LayoutSection -> Metadata.LayoutColumn objects -> Metadata.LayoutItem objects
        List<Metadata.Metadata> componentList = Metadata.Operations.retrieve(Metadata.MetadataType.Layout, componentNameList);
        if(componentList?.size() > 0){
            Metadata.Layout layout = (Metadata.Layout) componentList.get(0);
            List<Metadata.LayoutSection> layoutSectionList = layout.layoutSections;
            return layoutSectionList;
        }
        else{
            return null;
        }
    }
    public static void Foo(){
        string query = 'SELECT Layout.Name, Layout.TableEnumOrId, ProfileId, Profile.Name, RecordTypeId FROM ProfileLayout where recordtypeid=\'01210000000QfWdAAK\'';
        String baseURL = URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v41.0/tooling/query?q='+ query.replace(' ', '+');
        HttpResponse resp = null;
        HttpRequest req = new HttpRequest();
        req.setMethod('GET');
        req.setHeader('Authorization', 'Bearer ' + UserInfo.getsessionid());
        req.setEndpoint(baseURL);
        Http client = new Http();
        resp = client.send(req);
        Map<string,object> mso = (Map<string,object>)JSON.deserializeUntyped(resp.getBody());
        for(string key : mso.keySet()){
            system.debug('key='+key);
            system.debug(mso.get(key));
        }
        mso = (Map<string,object>)(((List<object>)mso.get('records'))[0]);
        for(string key : mso.keySet()){
            system.debug('key='+key);
            system.debug(mso.get(key));
        }
    }
}
force-app/main/default/classes/TestClass.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/TestController.cls
New file
@@ -0,0 +1,15 @@
public without sharing class TestController extends NewAndEditBaseController
{
    public TestController(ApexPages.StandardController controller) {
        List<String> fieldList = new List<String>(Schema.getGlobalDescribe().get('Inquiry_form__c').getDescribe().fields.getMap().keyset());
        // Add fields to controller. This is to avoid the SOQL error in visualforce page
        controller.addFields(fieldList);
        LookUpOverrideFields.add('Contact_Name__c');
        //添加项
        Init(controller.getRecord());
        system.debug(LookUpOverrideFieldsMapJson);
    }
}
force-app/main/default/classes/TestController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/classes/ViewParticipantsController.cls
New file
@@ -0,0 +1,6 @@
global class ViewParticipantsController {
    public String staticResourceContact {get; set;}
    public ViewParticipantsController(ApexPages.StandardController controller) {
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
    }
}
force-app/main/default/classes/ViewParticipantsController.cls-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexClass>
force-app/main/default/pages/B_Test.page
New file
@@ -0,0 +1,304 @@
<apex:page id="Page" controller="B_Test" sidebar="false" showHeader="false" action="{!init}">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script type="text/javascript">
    var staticResources = JSON.parse('{!staticResource}');
        var awsResult = [{
            "dataId": "942720697313001472",
            "isDelete": 0,
            "lastName": "张三12312321",
            "phone": "2988a8e6bcc90e83f54f81bc841aa822",
            "email": "d0152175c99a1c050f46d0d23996ff987b738add75e73c476b65611ba4a2b1b5",
            "medicalStaffFullName": null,
            "mobilePhone": "2988a8e6bcc90e83f54f81bc841aa822",
            "title": null,
            "olyAssistantType": null,
            "jobCategoryPicklist": null,
            "type": "3b13e2b5c5fd4003a931a38dcaf1c545",
            "contactAddress": null,
            "contactType": null,
            "doctorDivision1": null,
            "uniqueNumber": null,
            "lastNameEncrypt": null,
            "phoneEncrypt": null,
            "emailEncrypt": null,
            "medicalStaffFullNameEncrypt": null,
            "mobilePhoneEncrypt": null,
            "titleEncrypt": null,
            "olyAssistantTypeEncrypt": null,
            "jobCategoryPicklistEncrypt": null,
            "typeEncrypt": null,
            "contactAddressEncrypt": null,
            "contactTypeEncrypt": null,
            "doctorDivision1Encrypt": null,
            "uniqueNumberEncrypt": null
        },{
            "dataId": "942720697313001472",
            "isDelete": 0,
            "lastName": "李四12312321",
            "phone": "2988a8e6bcc90e83f54f81bc841aa822",
            "email": "d0152175c99a1c050f46d0d23996ff987b738add75e73c476b65611ba4a2b1b5",
            "medicalStaffFullName": null,
            "mobilePhone": "2988a8e6bcc90e83f54f81bc841aa822",
            "title": null,
            "olyAssistantType": null,
            "jobCategoryPicklist": null,
            "type": "3b13e2b5c5fd4003a931a38dcaf1c545",
            "contactAddress": null,
            "contactType": null,
            "doctorDivision1": null,
            "uniqueNumber": null,
            "lastNameEncrypt": null,
            "phoneEncrypt": null,
            "emailEncrypt": null,
            "medicalStaffFullNameEncrypt": null,
            "mobilePhoneEncrypt": null,
            "titleEncrypt": null,
            "olyAssistantTypeEncrypt": null,
            "jobCategoryPicklistEncrypt": null,
            "typeEncrypt": null,
            "contactAddressEncrypt": null,
            "contactTypeEncrypt": null,
            "doctorDivision1Encrypt": null,
            "uniqueNumberEncrypt": null
        }];
        var now_edit_id = '';
        function sobjectToAws(){
            return {
                "LastName":"张三",
                "Phone":"13800138000"
            }
        }
        function searchContactJs() {
            blockme();
            searchContact();
        }
        function editContactJs(conid) {
            blockme();
            now_edit_id=conid;
            editContact(conid);
        }
        function editSaveJs() {
            blockme();
            ProcessPI({},GetEditObj());
        }
        function editClearJs() {
            blockme();
            editClear();
        }
        function setContact(line) {
            var openLine = '{!openLine}';
            var cm = 'allPage:allForm:allBlock:records:'+ (openLine - 1) + ':contact';
            var cmid = 'allPage:allForm:allBlock:records:'+ (openLine - 1) + ':contactId';
            var conid = j$(escapeVfId('Page:allForm:listBlock:lineinfo:' + (line - 1) + ':conId')).value();
            var conname = j$(escapeVfId('Page:allForm:listBlock:lineinfo:' + (line - 1) + ':conName')).value();
            j$(escapeVfId(cmid),window.opener.document).val(conid);
            j$(escapeVfId(cm),window.opener.document).val(conname);
            // SWAG-BB44G7  设置所在科室名字和id的位置和内容 start
            var department = 'allPage:allForm:allBlock:records:'+ (openLine - 1) + ':department';
            var departmentid = 'allPage:allForm:allBlock:records:'+ (openLine - 1) + ':departmentid';
            var departmentHidden = 'allPage:allForm:allBlock:records:'+ (openLine - 1) + ':departmentHidden';
            var departmentHiddenId = 'allPage:allForm:allBlock:records:'+ (openLine - 1) + ':departmentHiddenId';
            var accid = j$(escapeVfId('Page:allForm:listBlock:lineinfo:' + (line - 1) + ':accountid')).value();
            var accName = j$(escapeVfId('Page:allForm:listBlock:lineinfo:' + (line - 1) + ':accountName')).value();
            j$(escapeVfId(department),window.opener.document).val(accName);
            j$(escapeVfId(departmentid),window.opener.document).val(accid);
            j$(escapeVfId(departmentHidden),window.opener.document).val(accName);
            j$(escapeVfId(departmentHiddenId),window.opener.document).val(accid);
            // SWAG-BB44G7  设置所在科室名字和id的位置和内容 end
            window.close();
        }
        jQuery(function(){
            alert("Init返回之后,继续查询AWS");
        })
/*
        function insertOrUpdateBack(payloadJson, r, isNewMode){
            payloadJson.LastName = r.object[0].lastName;
            payloadJson.Phone = r.object[0].phone;
            payloadJson.LastName_Encrypted__c = r.object[0].lastNameEncrypted;
            payloadJson.Phone_Encrypted__c = r.object[0].phoneEncrypted;
            payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            return payloadJson;
        }*/
        var aws_result = {};
        function GetAWSResultObj(){
            if(aws_result && aws_result.object && aws_result.object.length > 0){
                return aws_result.object[0];
            }
            return null;
        }
        function ProcessPI(sobjJson, payloadForNewPI) {
            //blockme();
            let url = staticResources.newUrl
            if (now_edit_id) {
                url = staticResources.updateUrl
            }
            AWSService.post(staticResources.updateUrl, payloadForNewPI, function(result){
                aws_result = result;
                SetEditObj();
                saveNew();
            }, staticResources.token);
        }
        function Trans(){
            let status = aws_result.status == '0';
            AWSService.sfdcBack({status:status}, aws_result, aws_result.txId, staticResources.token, staticResources.transactionURL,function(){
                unblockUI();
            })
        }
    </script>
    <apex:form id="allForm">
        <apex:actionFunction name="searchContact" action="{!searchContact}" rerender="allForm" onComplete="unblockUI();">
        </apex:actionFunction>
        <apex:actionFunction name="editContact" action="{!editContact}" rerender="allForm" onComplete="unblockUI();assignUnencrypted()">
            <apex:param name="firstParam" assignTo="{!conId}" value="" />
        </apex:actionFunction>
        <apex:actionFunction name="saveNew" action="{!saveNew}" rerender="allForm" onComplete="Trans();">
        </apex:actionFunction>
        <apex:actionFunction name="editClear" action="{!editClear}" rerender="allForm" onComplete="unblockUI();">
        </apex:actionFunction>
        <apex:outputPanel id="allPanel">
            <apex:pageBlock id="searchBlock" title="检索条件">
                <table class="linetable" border="0" style="border-collapse: collapse;width:600px;table-layout:fixed;">
                    <colgroup>
                        <col width="50px" />
                        <col width="150px" />
                        <col width="50px" />
                        <col width="150px" />
                        <col width="200px" />
                    </colgroup>
                    <tr>
                        <td>{!$ObjectType.Contact.fields.LastName.Label}</td>
                        <td><apex:inputField value="{!searchCon.Search_LastName__c}" style="width: 90%"/></td>
                        <td>{!$ObjectType.Contact.fields.FirstName.Label}</td>
                        <td><apex:inputField value="{!searchCon.Search_FirstName__c}" style="width: 90%"/></td>
                        <td><input type="button" value="检索" onclick="searchContactJs(); return null;" /></td>
                    </tr>
                </table>
            </apex:pageBlock>
            <apex:pageBlock id="listBlock" title="检索结果">
            <div style="height: 200px; overflow-y: auto; overflow-x: hidden;">
                <table class="edittable" border="0" style="border-collapse: collapse;width:580px;table-layout:fixed;">
                    <colgroup>
                        <col width="50px" />
                        <col width="100px" />
                        <col width="380px" />
                        <col width="50px" />
                    </colgroup>
                    <tr>
                        <th>No.</th>
                        <th>{!$ObjectType.Contact.fields.Name.Label}</th>
                        <th>{!$ObjectType.Contact.fields.AccountName__c.Label}</th>
                        <th>操作</th>
                    </tr>
                    <apex:repeat id="lineinfo" value="{!lineInfoList}" var="lineinfo">
                    <tr>
                        <td>{!lineinfo.lineNo}
                            <apex:inputHidden id="conId" value="{!lineinfo.con.id}"/>
                            <apex:inputHidden id="conName" value="{!lineinfo.con.name}"/>
                            <apex:inputHidden id="accountName" value="{!lineinfo.con.AccountName__c}"/>
                            <apex:inputHidden id="accountid" value="{!lineinfo.con.accountid}"/>
                        </td>
                        <td><a href="#" onclick="setContact('{!lineinfo.lineNo}');">{!lineinfo.con.Name}</a></td>
                        <td>{!lineinfo.con.AccountName__c}</td>
                        <td><input style="width:90%;" type="button" value="编辑" onclick="editContactJs('{!lineinfo.con.Id}'); return null;" /></td>
                    </tr>
                    </apex:repeat>
                </table>
            </div>
            </apex:pageBlock>
            <script>
                function assignUnencrypted(){
                    let obj = sobjectToAws();
                    document.getElementById("Page:allForm:editBlock:Search_LastName__c").value = obj.LastName;
                    document.getElementById("Page:allForm:editBlock:Phone").value = obj.Phone;
                }
                function GetEditObj(){
                    return JSON.stringify([{
                        lastName : document.getElementById("Page:allForm:editBlock:Search_LastName__c").value,
                        phone : document.getElementById("Page:allForm:editBlock:Phone").value,
                        dataId:document.getElementById("Page:allForm:editBlock:AWS_Data_Id__c").value,
                    }]);
                }
                function SetEditObj(){
                    let obj = GetAWSResultObj();
                    if(obj){
                        document.getElementById("Page:allForm:editBlock:Search_LastName__c").value = obj.lastName;
                        document.getElementById("Page:allForm:editBlock:LastName_Encrypted__c").value = obj.lastNameEncrypt;
                        document.getElementById("Page:allForm:editBlock:Phone").value = obj.phone;
                        document.getElementById("Page:allForm:editBlock:Phone_Encrypted__c").value = obj.phoneEncrypt;
                    }
                }
            </script>
            <apex:pageBlock id="editBlock" title="联系人编辑">
                <apex:pageBlockButtons location="top">
                    <apex:commandButton onclick="editClearJs();" value="清空" rerender="dummy"/>
                    <apex:commandButton onclick="editSaveJs();" value="保存" rerender="dummy"/>
                </apex:pageBlockButtons>
                <apex:inputHidden id="LastName_Encrypted__c" value="{!newCon.LastName_Encrypted__c}"/>
                <apex:inputHidden id="Phone_Encrypted__c" value="{!newCon.Phone_Encrypted__c}"/>
                <apex:inputHidden id="AWS_Data_Id__c" value="{!newCon.AWS_Data_Id__c}"/>
                <table class="edittable" border="0" style="border-collapse: collapse; width:600px; table-layout:fixed;">
                    <colgroup>
                        <col width="50px" />
                        <col width="150px" />
                        <col width="50px" />
                        <col width="150px" />
                        <col width="50px" />
                        <col width="150px" />
                    </colgroup>
                    <tr>
                        <td>{!$ObjectType.Contact.fields.LastName.Label}</td>
                        <td><span><div class="requiredInput"><div class="requiredBlock"></div>
                            <apex:inputField id="Search_LastName__c" value="{!newCon.Search_LastName__c}" style="width: 90%"/>
                        </div></span></td>
                        <td>{!$ObjectType.Contact.fields.Phone.Label}</td>
                        <td><apex:inputField id="Phone" value="{!newCon.Phone}" style="width: 90%"/></td>
                    </tr>
                    <tr>
                        <td>{!$ObjectType.Contact.fields.Supplement__c.Label}</td>
                        <td colspan="5"><apex:inputField id="Supplement__c" value="{!newCon.Supplement__c}" style="width: 95%; resize: none; height: 50px"/></td>
                    </tr>
                </table>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>
</apex:page>
force-app/main/default/pages/B_Test.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>B_Test</label>
</ApexPage>
force-app/main/default/pages/ConsumApplyUploadPdf.page
New file
@@ -0,0 +1,190 @@
<!-- 该页面用于Lead对象上传PDF,未来如果要添加其他对象的上传PDF功能,复制该页面,将**standardController**修改为其他对象API名称即可 -->
<apex:page standardController="Consum_Apply__c" extensions="FileUploadController" id="page" lightningStyleSheets="true">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script>
        var staticResources = JSON.parse('{!staticResource}');
        var parentId = '{!parentId}';
        var uploadUrl = staticResources.newUrl;
        var key;
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:theForm:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'message errorM3';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:theForm:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        function getFileContent(event) {
            var fileObject = document.getElementById("page:theForm:block:uploadSection:file");
            var reader = new FileReader();
            var data = reader.readAsDataURL(fileObject.files[0]);
            debugger
            console.log(event);
        }
        function getBase64(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = () => resolve(reader.result);
                reader.onerror = error => reject(error);
            });
        }
        function disableButtonStatus() {
            let btnNode = document.getElementById('uploadFileId');
            btnNode.classList.add("btnDisabled");
        }
        function enableButtonStatus() {
            let btnNode = document.getElementById('uploadFileId');
            btnNode.classList.remove("btnDisabled");
        }
        function uploadFile() {
            disableButtonStatus();
            var fileObject = document.getElementById("file").files[0];
            getBase64(fileObject).then(
                data => {
                    console.log(data);
                    uploadFileToAWS(data, (fileObject.size).toString(), fileObject.name);
                }
            );
        }
        function confirmTrans(transId, isSuccess) {
            fetch(staticResources.updateUrl, {
                method: 'POST',
                body: JSON.stringify({ 'txId': transId, "isSuccess": isSuccess }),
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then(data => {
                console.log("confirmTrans-" + JSON.stringify(data));
                document.getElementById("file").files[0].name = '';
                enableButtonStatus();
                refreshFiles();
                return data.status;
            })
        }
        function calculateFileSize(fileObject) {
            if (fileObject.size > 20971520) {
                alertErrorMessage('文件过大,请选择小于20mb的文件');
            }
        }
        function uploadFileToAWS(data, size, fileName) {
            console.log("body=" + JSON.stringify({ 'file': data, "size": size, 'fileName': fileName }));
            fetch(uploadUrl, {
                method: 'POST',
                body: JSON.stringify({ 'file': data, "size": size, 'fileName': fileName }),
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then(result => {
                console.log("result" + JSON.stringify(result));
                if (result.success == true) {
                    key = result.object;
                    Visualforce.remoting.Manager.invokeAction(
                        '{!$RemoteAction.FileUploadController.saveFile}',
                        fileName, key, result.txId, parentId,
                        function (resultvalue, event) {
                            //2. show file list
                            if (resultvalue.status == 'fail') {
                                alertErrorMessage(resultvalue.message);
                                //1. Confirm trans
                                confirmTrans(result.txId, 0);
                            } else {
                                alertErrorMessage('上传成功');
                                confirmTrans(result.txId, 1);
                            }
                            // window.location.reload();
                        },
                        { escape: true }
                    );
                    console.log('key' + key);
                } else {
                    alertErrorMessage('上传失败请稍后再试!');
                }
            }).catch((error) => {
                console.error('Error:', error);
            })
            debugger
        }
        function downPdf(fileUrl) {
            window.open(fileUrl,'_blank');
        }
    </script>
    <style>
        .pdf .num {
            width: 30%;
        }
        .pdf.name {
            width: 30%
        }
        .pdf.downLink {
            width: 40%
        }
    </style>
    <apex:form id="theForm">
        <apex:actionFunction name="refreshFiles" action="{!refreshFiles}" reRender="pdf,uploadSection"/>
        <br/>
        <br/>
        <apex:pageBlock id="block">
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <apex:pageBlockSection id="uploadSection">
                <!-- <apex:inputFile id="file" value="{!documentData.body}" filename="{!documentData.name}" /> -->
                <input type="file" id="file" name="filename"/>
                <input class="btn" id='uploadFileId' type="Button" value="确认上传" onclick="uploadFile()" />
            </apex:pageBlockSection>
        </apex:pageBlock>
        <apex:pageBlock title="PDF列表" id="pdf">
            <!-- <apex:pageBlockSection > -->
            <!-- show uploated file list -->
            <apex:pageBlockTable value="{!fileList}" var="file" align="center" columns="3" columnsWidth="30%,30%,40%">
                <apex:column id="name" headerValue="文件名称">
                    <apex:outputLink value="/{!file.Id}" target="_blank">{!file.FileName__c}</apex:outputLink>
                </apex:column>
                <!-- <apex:column id="num" headerValue="父记录链接">
                    <apex:outputLink value="/{!file.ParentRecordId__c}" target="_blank">{!file.ParentRecordId__c}</apex:outputLink>
                </apex:column> -->
                <apex:column id="previewLink" headerValue="预览链接">
                    <apex:outputLink value="{!file.ViewLink__c}" target="{!file.ViewLink__c}">预览链接
                    </apex:outputLink>
                </apex:column>
                <apex:column id="downLink" headerValue="下载链接">
                    <!-- <apex:outputLink value= "{!file.DownloadLink__c}" target="{!file.DownloadLink__c}">下载链接
                    </apex:outputLink> -->
                    <input class="btn" id='downloadFileButton' type="Button" value="下载" onclick="downPdf('{!file.DownloadLink__c}')" />
                </apex:column>
            </apex:pageBlockTable>
            <!-- </apex:pageBlockSection> -->
        </apex:pageBlock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ConsumApplyUploadPdf.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ConsumApplyUploadPdf</label>
</ApexPage>
force-app/main/default/pages/NewAndEditASEActivity.page
New file
@@ -0,0 +1,526 @@
<apex:page standardController="ASEActivity__c" extensions="NewAndEditASEActivityController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let ele = GetEleByClass(config.ApiPrefix + "_"+ config.AWSToSobjectNonEncryptedMap[f]);
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                            if(ele && data.object[f]){
                                let arr = data.object[f].split(';');
                                // 给隐藏的select赋值
                                for(let op of ele.options){
                                    op.selected = arr.indexOf(op.value)>-1;
                                }
                                // 利用按钮给显示的select赋值
                                let ra = document.getElementById(ele.id + '_right_arrow');
                                if(ra){
                                    ra.click();
                                }
                            }
                            }else{
                                ele.value = data.object[f];
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                // document.querySelector("[data-id='Phone']").value = data.object.phone;
                // document.querySelector("[data-id='Email']").value = data.object.email;
            },
            updateMethod:"NewAndEditASEActivityController.saveASEActivity",
            insertMethod:"NewAndEditASEActivityController.saveASEActivity"
        }
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var staticResources = JSON.parse('{!staticResource}');
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormElement(tag_name){
            return ['input','select','textarea'].indexOf(tag_name)>-1;
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            // let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='CustomerTel__c']";
            // //Email
            // let email = document.querySelector(textEmail);
            // if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
            //     error_msg += ';邮件格式错误';
            // }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                let ele = nodelist[index];
                let field_api_name = GetEleApiName(ele);
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormElement(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets;
                } else {
                    result[field_api_name] = ele.value;
                }
            }
            return result;
        }
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
            unblockUI();
        };
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. ASEActivity to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        var newSearchContactWindow = null;
        var contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        function searchContact(contactNodeId){
            // errorMsg 隐藏
            if(document.getElementsByClassName("errorMsg").length > 0){
                document.getElementsByClassName("errorMsg")[0].style.display="none";
            }
            let accountValue = "";
            let suffixUrl = "";
            if (document.querySelector("[data-id='Department__c']")) {
                let accountNodeId = document.querySelector("[data-id='Department__c']").id + '_lkid';
                accountValue = document.getElementById(accountNodeId).value;
            }
            console.log('accountValue = ' + accountValue);
            if(accountValue !='000000000000000'){
                suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
            }else{
                suffixUrl = "?contactId="+contactNodeId;
            }
            let baseUrl = "/apex/SearchContactPage";
            let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
            newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
            if (window.focus) {
                newSearchContactWindow.focus();
            }
            return false;
        }
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page:form:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id='ReporterASE__c']").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id='ReporterASE__c']").value = contactInfo.Name;
        }
        function replaceSearchContactLookup() {
            let lookUpNode = htmlToElement(contactHtmlString);
            console.log(lookUpNode);
            if (!{!isNewMode}) {
                //1. Query Contact from AWS by AWSDataId
                queryContactName()
            }
            let parentNode = document.querySelector("[data-id='ReporterASE__c']").parentNode;
            document.querySelector("[data-id='ReporterASE__c']").removeAttribute("onchange");
            parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='ReporterASE__c']").parentNode.children[2]);
        }
        function queryContactName() {
            let sfId = document.getElementById(document.querySelector("[data-id='ReporterASE__c']").id + '_lkid').value;
            let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
            let dataId = contactsInfo[sfId];
            let queryContactBack = function(data){
                //To Do later
                console.log('ContactData = ' + data.object);
                document.querySelector("[data-id='ReporterASE__c']").value = data.object.lastName;
            }
            AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
            // let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
            // fetch(url, {
            //     method: 'GET',
            //     headers: {
            //         'Content-Type': 'application/json',
            //         'pi-token': staticResources.token
            //     }
            // }).then((data) => {
            //     return data.json();
            // }).then((result) => {
            //     document.querySelector("[data-id='ReporterASE__c']").value = result.object.lastName;
            // })
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:inputHidden value="{!contactId}" id="contactId"/>
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!ASEActivity__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Sobject Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QuerySobjectFromAWS();
                    }
                    //Replace Vlookup Field
                    replaceSearchContactLookup();
                    document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
                    document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditASEActivity.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditASEActivity</label>
</ApexPage>
force-app/main/default/pages/NewAndEditAddress.page
New file
@@ -0,0 +1,427 @@
<apex:page standardController="Address__c" extensions="NewAndEditAddressController" id="page">
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var redirectMode = 'Save';//1. Save 2. SaveAndNew
        var requiredAPIToChangedLabelMap = new Map();
        requiredAPIToChangedLabelMap.set('LastName', '{!PIPL_Name_Label}');
        console.log('{!contactsInfo}');
        var VLookUpFields = new Set(['Contacts__c', 'Province__c', 'City__c', 'Customer__c']);
        function ProcessPI(addressJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(addressJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(addressJson, payloadForNewPI)
            }
        }
        function enableButton(obj){
            obj.classList.remove("btnDisabled");
        }
        function disableButton(obj){
            obj.classList.add("btnDisabled");
        }
        function disableButtonStatus(){
            let btnList = document.getElementsByClassName('btn');
            for(let i=0;i<btnList.length;i++){
                disableButton(btnList[i]);
            }
        }
        function enableButtonStatus(){
            let btnList = document.getElementsByClassName('btn');
            for(let i=0;i<btnList.length;i++){
                enableButton(btnList[i]);
            }
        }
        function getPIPayload(addressJson) {
            let addressPayloadList = [];
            let Telephone = addressJson.Telephone__c;
            let ZipCode = addressJson.ZipCode__c;
            let DetailedAddress = addressJson.Detailed_Address__c;
            let addressPIData = new Object();
            addressPIData.telephone = Telephone;
            addressPIData.zipCode = ZipCode;
            addressPIData.detailedAddress = DetailedAddress;
            addressPIData.sfRecordId = '';
            console.log('Address PI Data:' + addressPIData);
            addressPayloadList.push(addressPIData);
            console.log(JSON.stringify(addressPayloadList));
            return JSON.stringify(addressPayloadList);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            // let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='Telephone__c']";
            //Email
            // let email = document.querySelector(textEmail);
            // if(email && !/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/.test(email.value)){
            //     error_msg += ';邮件格式错误';
            // }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getAddressInformation() {
            let nodelist = document.querySelectorAll("[data-id]");
            let result = {}
            result.RecordTypeId = '{!rtTypeId}';
            for (let index = 0; index < nodelist.length; index++) {
                if (VLookUpFields.has(nodelist[index].getAttribute("data-id"))) {
                    console.log(nodelist[index].id.indexOf('lkwgt'));
                    if (nodelist[index].id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = nodelist[index].id + '_lkid';
                        let vlookUpNodeValue = document.getElementById(vlookUpNodeId).value;
                        result[nodelist[index].getAttribute("data-id")] = vlookUpNodeValue;
                    }
                } else if (nodelist[index].type == 'checkbox') {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].checked;
                } else if (nodelist[index].type == 'select-multiple') {
                    //nodelist[index].getAttribute("data-id")
                    let multiple = nodelist[index].getAttribute("data-id");
                    let targets = document.querySelector("[data-id=" + multiple + "]").parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[nodelist[index].getAttribute("data-id")] = targets;
                } else {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].value;
                }
                let x = index + 1;
                if (x <= nodelist.length - 1 && (nodelist[x].getAttribute("data-id") == nodelist[index].getAttribute("data-id"))) {
                    index++;
                }
            }
            return result;
        }
        function QueryAddressFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        var queryBack = function queryBack(data) {
            console.log('data = ' + data);
            document.querySelector("[data-id='Telephone__c']").value = data.object.telephone;
            document.querySelector("[data-id='ZipCode__c']").value = data.object.zipCode;
            document.querySelector("[data-id='Detailed_Address__c']").value = data.object.detailedAddress;
            unblockUI();
        };
        var insertOrUpdateBack = function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            payloadJson.Telephone__c = r.object[0].telephone;
            payloadJson.ZipCode__c = r.object[0].zipCode;
            payloadJson.Detailed_Address__c = r.object[0].detailedAddress;
            payloadJson.Telephone_Encrypted__c = r.object[0].telephoneEncrypt;
            payloadJson.ZipCode_Encrypted__c = r.object[0].zipCodeEncrypt;
            payloadJson.Detailed_Address_Encrypted__c = r.object[0].detailedAddressEncrypt;
            //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            if (isNewMode) {
                payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            } else {
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            }
            return payloadJson;
        }
        var redirectCallBack = function redirectCallBack(sfId,errorMessage) {
            if(sfId){
                if(redirectMode == 'Save'){
                    window.open('/' + sfId, '_self');
                }else if(redirectMode == 'SaveAndNew'){
                    window.open('/' + sfId + '/e?retURL=%2F' + sfId + '=%2Fo', '_self');
                }
            }else{
                // alert(errorMessage);
                alertErrorMessage(errorMessage);
            }
        }
        function UpdatePIToAWS(addressJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewAndEditAddressController.saveAddress}';
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, addressJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(addressJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewAndEditAddressController.saveAddress}';
            AWSService.insert(staticResources.newUrl, addressJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    let fieldAPIValue = requiredFieldAPIList[i]
                    let fieldLabelValue = fieldAPIToLabelMap[fieldAPIValue];
                    if (requiredAPIToChangedLabelMap.has(fieldAPIValue)) {
                        fieldLabelValue = requiredAPIToChangedLabelMap.get(fieldAPIValue);
                    }
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveAddressProcess(saveMode) {
            disableButtonStatus();
            redirectMode = saveMode;
            console.log('redirectMode'+redirectMode);
            hiddenErrorMsgNode();
            //1. Get Address Information from Form
            let addressJson = getAddressInformation();
            //2. Validate the Address field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(addressJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('{!Input_Required_Field_Msg}'+checkRequiredFieldMsgResult);
                return
            }
            //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(addressJson);
            //4. Address to AWS
            ProcessPI(addressJson, payloadForNewPI);
        }
        function alertErrorMessage(errorMsg) {
            enableButtonStatus();
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsg = '错误:无效数据。'+'\n' + errorMsg;
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
            unblockUI();
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        var newSearchContactWindow = null;
        var contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        function searchContact(contactNodeId) {
            //1. Check account value
            let accountNodeId = document.querySelector("[data-id='Customer__c']").id + '_lkid';
            let accountValue = document.getElementById(accountNodeId).value;
            console.log(accountValue);
            if (accountValue != '000000000000000') {
                let baseUrl = "/apex/SearchContactPage";
                let suffixUrl = "?contactId=" + contactNodeId + "&accountId=" + accountValue;
                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
                newSearchContactWindow = window.open(baseUrl + suffixUrl, 'Popup', newSearchContactParam);
                if (window.focus) {
                    newSearchContactWindow.focus();
                }
                return false;
            } else {
                //alertErrorMessage('{!PIPL_Input_Account_Error_Msg}');
                alertErrorMessage('请先选择客户');
            }
        }
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page:form:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id='Contacts__c']").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id='Contacts__c']").value = contactInfo.Name;
        }
        function replaceSearchContactLookup() {
            let lookUpNode = htmlToElement(contactHtmlString);
            console.log(lookUpNode);
            if (!{!isNewMode}) {
                //1. Query Contact from AWS by AWSDataId
                queryContactName()
                // document.querySelector("[data-id='Contacts__c']").value = '王奎';
            }
            let parentNode = document.querySelector("[data-id='Contacts__c']").parentNode;
            document.querySelector("[data-id='Contacts__c']").removeAttribute("onchange");
            parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Contacts__c']").parentNode.children[2]);
        }
        function queryContactName() {
            let sfId = document.getElementById(document.querySelector("[data-id='Contacts__c']").id + '_lkid').value;
            let contactsInfo = JSON.parse('{!contactsInfo}');
            let dataId = contactsInfo[sfId];
            let queryContactBack = function(data){
                //To Do later
                console.log('ContactData = ' + data.object);
                document.querySelector("[data-id='Contacts__c']").value = data.object.lastName;
            }
            AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
            // let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
            // fetch(url, {
            //     method: 'GET',
            //     headers: {
            //         'Content-Type': 'application/json',
            //         'pi-token': staticResources.token
            //     }
            // }).then((data) => {
            //     return data.json();
            // }).then((result) => {
            //     document.querySelector("[data-id='Contacts__c']").value = result.object.lastName;
            // })
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="收货地址" class="pageTitleIcon" title="收货地址" />
                <h1 class="pageType">收货地址编辑
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> 新建收货地址</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target=address_edit.htm&amp;section=Address&amp;language=zh_CN&amp;release=234.18.14&amp;instance=CS58&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:inputHidden value="{!contactId}" id="contactId"/>
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">收货地址编辑</h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveAddressProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveAddressProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <br/>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" showHeader="{!layoutSection.useHeader}" collapsible="{!layoutSection.allowCollapse}"
                    columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField html-data-id="{!layoutField.fieldAPI}" value="{!Address__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Address Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();//for loading search by Li Jun 20220218
                        QueryAddressFromAWS();
                    }
                    //Replace Vlookup Field
                    replaceSearchContactLookup();
                    //3. Set Readonly Attribute
                // document.querySelector("[data-id='OwnerId']").classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveAddressProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveAddressProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditAddress.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditAddress</label>
</ApexPage>
force-app/main/default/pages/NewAndEditAgencyContact.page
New file
@@ -0,0 +1,511 @@
<apex:page standardController="Agency_Contact__c" extensions="NewAndEditAgencyContactController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script>
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                if('{!rtTypeId}'){
                    payloadJson.RecordTypeId = '{!rtTypeId}';
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let ele = GetEleByClass(config.ApiPrefix + "_"+ config.AWSToSobjectNonEncryptedMap[f]);
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                               if(ele && data.object[f]){
                                   let arr = data.object[f].split(';');
                                   // 给隐藏的select赋值
                                   for(let op of ele.options){
                                       op.selected = arr.indexOf(op.value)>-1;
                                   }
                                   // 利用按钮给显示的select赋值
                                   let ra = document.getElementById(ele.id + '_right_arrow');
                                   if(ra){
                                       ra.click();
                                   }
                               }
                            }else{
                                ele.value = data.object[f];
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                // document.querySelector("[data-id='Phone']").value = data.object.phone;
                // document.querySelector("[data-id='Email']").value = data.object.email;
            },
            updateMethod:"NewAndEditAgencyContactController.saveContact",
            insertMethod:"NewAndEditAgencyContactController.saveContact"
        }
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormElement(tag_name){
            return ['input','select','textarea'].indexOf(tag_name)>-1;
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='Phone']";
            //Email
            let email = document.querySelector(textEmail);
            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
                error_msg += ';邮件格式错误';
            }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                let ele = nodelist[index];
                let field_api_name = GetEleApiName(ele);
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormElement(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets;
                } else {
                    result[field_api_name] = ele.value;
                }
            }
            return result;
        }
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
            unblockUI();
        };
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. lead to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        var newSearchContactWindow = null;
        var contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page_form_contactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        //自定义lookup查询
        function searchContact(contactNodeId){
            let accountValue = "";
            // if (document.querySelector("[data-id='Account__c']")) {
            //     let accountNodeId = document.querySelector("[data-id='Account__c']").id + '_lkid';
            //     accountValue = document.getElementById(accountNodeId).value;
            // }
            console.log(accountValue);
            if(true || accountValue !='000000000000000'){
                let baseUrl = "/apex/SearchContactPage";
                let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
                if (window.focus) {
                    newSearchContactWindow.focus();
                }
                return false;
            }else{
                alertErrorMessage('{!$Label.PIPL_Input_Account_Error_Msg}');
            }
        }
        //窗口关闭时发生
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page_form_contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id='Contact__c']").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id='Contact__c']").value = contactInfo.Name;
        }
        //替换vlookup
        function replaceSearchContactLookup() {
            let lookUpNode = htmlToElement(contactHtmlString);
            console.log(lookUpNode);
            if (!{!isNewMode}) {
                //1. Query Contact from AWS by AWSDataId
                // document.querySelector("[data-id='ContactId']").value = '王奎';
                queryContactName()
            }
            let parentNode = document.querySelector("[data-id='Contact__c']").parentNode;
            document.querySelector("[data-id='Contact__c']").removeAttribute("onchange");
            parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Contact__c']").parentNode.children[2]);
        }
        function queryContactName() {
            let sfId = document.getElementById(document.querySelector("[data-id='Contact__c']").id + '_lkid').value;
            let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
            let dataId = contactsInfo[sfId];
            let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
            fetch(url, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then((result) => {
                document.querySelector("[data-id='Contact__c']").value = result.object.lastName;
            })
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <input type="hidden"  id="page_form_contactId"/>
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Agency_Contact__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Sobject Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QuerySobjectFromAWS();
                    }
                    //Replace Vlookup Field
                    replaceSearchContactLookup();
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditAgencyContact.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditAgencyContact</label>
</ApexPage>
force-app/main/default/pages/NewAndEditCampaignMember.page
New file
@@ -0,0 +1,421 @@
<apex:page standardController="CampaignMember__c" extensions="NewAndEditCampaignMemberController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script>
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let ele = GetEleByClass(config.ApiPrefix + "_"+ config.AWSToSobjectNonEncryptedMap[f]);
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                               if(ele && data.object[f]){
                                   let arr = data.object[f].split(';');
                                   // 给隐藏的select赋值
                                   for(let op of ele.options){
                                       op.selected = arr.indexOf(op.value)>-1;
                                   }
                                   // 利用按钮给显示的select赋值
                                   let ra = document.getElementById(ele.id + '_right_arrow');
                                   if(ra){
                                       ra.click();
                                   }
                               }
                            }else{
                                ele.value = data.object[f];
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
            },
            updateMethod:"NewAndEditCampaignMemberController.saveCampaignMember",
            insertMethod:"NewAndEditCampaignMemberController.saveCampaignMember"
        }
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormElement(tag_name){
            return ['input','select','textarea'].indexOf(tag_name)>-1;
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='Phone']";
            //Email
            let email = document.querySelector(textEmail);
            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
                error_msg += ';邮件格式错误';
            }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                let ele = nodelist[index];
                let field_api_name = GetEleApiName(ele);
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormElement(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets;
                } else {
                    result[field_api_name] = ele.value;
                }
            }
            return result;
        }
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
        };
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. lead to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!CampaignMember__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Sobject Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        QuerySobjectFromAWS();
                    }
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditCampaignMember.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditCampaignMember</label>
</ApexPage>
force-app/main/default/pages/NewAndEditCase.page
New file
@@ -0,0 +1,442 @@
<apex:page standardController="Case" extensions="NewAndEditCaseController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var redirectMode = "Save";
        var requiredAPIToChangedLabelMap = new Map();
        requiredAPIToChangedLabelMap.set('LastName', '{!PIPL_Name_Label}');
        console.log('{!contactsInfo}');
        var VLookUpFields = new Set(['Account__c', 'ContactId', 'Asset__c', 'prod__c', 'Competitor_info__c', 'AccountId', 'Field1_staff__c']);
        //判断insert or update
        function ProcessPI(caseJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(caseJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(caseJson, payloadForNewPI)
            }
        }
        //防止按钮重复点击
        function enableButton(obj){
            obj.classList.remove("btnDisabled");
        }
        function disableButton(obj){
            obj.classList.add("btnDisabled");
        }
        function disableButtonStatus(){
            let btnList = document.getElementsByClassName('btn');
            for(let i=0;i<btnList.length;i++){
                disableButton(btnList[i]);
            }
        }
        function enableButtonStatus(){
            let btnList = document.getElementsByClassName('btn');
            for(let i=0;i<btnList.length;i++){
                enableButton(btnList[i]);
            }
        }
        //获取加密字段
        function getPIPayload(caseJson) {
            let casePayloadList = [];
            let CicTelephone = caseJson.cic_telephone__c;
            let CaseCustomer = caseJson.CASE_CUSTOMER__c;
            let CustomerManual = caseJson.Customer_manual__c;
            let casePIData = new Object();
            casePIData.cicTelephone = CicTelephone;
            casePIData.caseCustomer = CaseCustomer;
            casePIData.customerManual = CustomerManual;
            casePIData.sfRecordId = '';
            console.log('Case PI Data:' + casePIData);
            casePayloadList.push(casePIData);
            console.log(JSON.stringify(casePayloadList));
            return JSON.stringify(casePayloadList);
        }
        //判断数据格式
        function validateFieldValueFormate() {
            //let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='cic_telephone__c']";
            if (!document.querySelector("[data-id='Account__c']")) {
                return true;
            }
            //Email
            //let email = document.querySelector(textEmail).value;
            let phone = document.querySelector(textPhone).value;
            if (phone == "") {
                return true;
            }
            //let regEmail = /^[\w-]{3,12}@[\da-zA-Z]{2,6}\.[a-zA-Z]+$/;
            let regPhone = /^1[3|5|8|7][0-9]\d{4,8}$/;
            //let emailFormate = regEmail.test(email);
            let phoneFormate = regPhone.test(phone);
            //console.log(emailFormate);
            console.log(phoneFormate);
            //if (emailFormate == true && phoneFormate == true) {
            if (phoneFormate == true) {
                return true;
            } else {
                return false;
            }
        }
        //获取表单数据
        function getCaseInformation() {
            let nodelist = document.querySelectorAll("[data-id]");
            let result = {}
            result.RecordTypeId = '{!rtTypeId}'
            for (let index = 0; index < nodelist.length; index++) {
                if (VLookUpFields.has(nodelist[index].getAttribute("data-id"))) {
                    console.log(nodelist[index].id.indexOf('lkwgt'));
                    if (nodelist[index].id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = nodelist[index].id + '_lkid';
                        let vlookUpNodeValue = document.getElementById(vlookUpNodeId).value;
                        result[nodelist[index].getAttribute("data-id")] = vlookUpNodeValue;
                    }
                } else if (nodelist[index].type == 'checkbox') {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].checked;
                } else if (nodelist[index].type == 'select-multiple') {
                    //nodelist[index].getAttribute("data-id")
                    let multiple = nodelist[index].getAttribute("data-id");
                    let targets = document.querySelector("[data-id=" + multiple + "]").parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[nodelist[index].getAttribute("data-id")] = targets;
                } else {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].value;
                }
                let x = index + 1;
                if (x <= nodelist.length-1 && (nodelist[x].getAttribute("data-id") == nodelist[index].getAttribute("data-id"))) {
                    index++;
                }
            }
            //针对id的手动添加
            if (document.getElementById("page:form:block:j_id31:0:j_id32:j_id33:1:j_id34_lkid") && (!result.hasOwnProperty("Field1_staff__c") || !result["Field1_staff__c"])){
                if(document.getElementById("page:form:block:j_id31:0:j_id32:j_id33:1:j_id34_lkid").value != '000000000000000'){
                    result["Field1_staff__c"] = document.getElementById("page:form:block:j_id31:0:j_id32:j_id33:1:j_id34_lkid").value;
                }
            }
            return result;
        }
        //查询
        function QueryCaseFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        //需要解密字段
        var queryBack = function queryBack(data) {
            console.log('data = ' + data);
            document.querySelector("[data-id='cic_telephone__c']").value = data.object.cicTelephone;
            document.querySelector("[data-id='CASE_CUSTOMER__c']").value = data.object.caseCustomer;
            document.querySelector("[data-id='Customer_manual__c']").value = data.object.customerManual;
        };
        var insertOrUpdateBack = function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            payloadJson.cic_telephone__c = r.object[0].cicTelephone;
            payloadJson.CASE_CUSTOMER__c = r.object[0].caseCustomer;
            payloadJson.Customer_manual__c = r.object[0].customerManual;
            payloadJson.cic_telephone_Encrypted__c = r.object[0].cicTelephoneEncrypt;
            payloadJson.CASE_CUSTOMER_Encrypted__c = r.object[0].caseCustomerEncrypt;
            payloadJson.Customer_manual_Encrypted__c = r.object[0].customerManualEncrypt;
            //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            if (isNewMode) {
                payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            } else {
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            }
            return payloadJson;
        }
        //回调函数,点击后事件
        var redirectCallBack = function redirectCallBack(sfId,errorMessage) {
            if(sfId){
                if(redirectMode == 'Save'){
                    window.open('/' + sfId, '_self');
                }else if(redirectMode == 'SaveAndNew'){
                    window.open('/setup/ui/recordtypeselect.jsp?ent='+'{!sobjecttypeForFrontEnd}'+'&retURL=/'+'{!sobjectPrefix}'+'/o&save_new_url=/'+'{!sobjectPrefix}'+'/e?retURL=%2F'+'{!sobjectPrefix}'+'%2Fo','_self');
                }else if(redirectMode == 'SaveAndClose'){
                    window.open('/' + sfId + '/s?retURL=%2F' + sfId + '&co=1', '_self');
                }
            }else{
                alertErrorMessage(errorMessage);
            }
        }
        //update to AWS
        function UpdatePIToAWS(caseJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewAndEditCaseController.saveCase}';
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, caseJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack, redirectCallBack);
        }
        //insert to AWS
        function NewPIToAWS(caseJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewAndEditCaseController.saveCase}';
            AWSService.insert(staticResources.newUrl, caseJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack, redirectCallBack);
        }
        //必填字段
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for (i = 0; i < requiredFieldAPIList.length; i++) {
                if (formData[requiredFieldAPIList[i]]) {
                    continue;
                } else {
                    let fieldAPIValue = requiredFieldAPIList[i]
                    let fieldLabelValue = fieldAPIToLabelMap[fieldAPIValue];
                    if (requiredAPIToChangedLabelMap.has(fieldAPIValue)) {
                        fieldLabelValue = requiredAPIToChangedLabelMap.get(fieldAPIValue);
                    }
                    if (blankRequiredFields == '') {
                        blankRequiredFields = blankRequiredFields + fieldLabelValue;
                    } else {
                        blankRequiredFields = blankRequiredFields + ',' + fieldLabelValue;
                    }
                }
            }
            return blankRequiredFields;
        }
        //按钮点击事件
        function saveCaseProcess(saveMode) {
            disableButtonStatus();
            redirectMode = saveMode;
            console.log('redirectMode'+redirectMode);
            hiddenErrorMsgNode();
            //1. Get Case Information from Form
            let caseJson = getCaseInformation();
            //2. Validate the Case field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (!validationResultMessage) {
                //Popup error message.  - To Do After POC
                //alertErrorMessage('邮箱格式输入有误,请重新输入!');
                alertErrorMessage('手机格式输入有误,请重新输入!');
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(caseJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('{!Input_Required_Field_Msg}'+checkRequiredFieldMsgResult);
                return
            }
            //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(caseJson);
            //4. Case to AWS
            ProcessPI(caseJson, payloadForNewPI);
        }
        //error 报错
        function alertErrorMessage(errorMsg) {
            enableButtonStatus();
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsg = '错误:无效数据。'+'\n' + errorMsg;
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
            unblockUI();
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        var newSearchContactWindow = null;
        var contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        //自定义lookup查询
        function searchContact(contactNodeId){
            let accountValue = "";
            if (document.querySelector("[data-id='Account__c']")) {
                let accountNodeId = document.querySelector("[data-id='Account__c']").id + '_lkid';
                accountValue = document.getElementById(accountNodeId).value;
            }
            console.log(accountValue);
            if(accountValue !='000000000000000'){
                let baseUrl = "/apex/SearchContactPage";
                let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
                if (window.focus) {
                    newSearchContactWindow.focus();
                }
                return false;
            }else{
                alertErrorMessage('{!PIPL_Input_Account_Error_Msg}');
            }
        }
        //窗口关闭时发生
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page:form:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id='ContactId']").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id='ContactId']").value = contactInfo.Name;
        }
        //替换vlookup
        function replaceSearchContactLookup() {
            let lookUpNode = htmlToElement(contactHtmlString);
            console.log(lookUpNode);
            if (!{!isNewMode}) {
                //1. Query Contact from AWS by AWSDataId
                // document.querySelector("[data-id='ContactId']").value = '王奎';
                queryContactName()
            }
            let parentNode = document.querySelector("[data-id='ContactId']").parentNode;
            document.querySelector("[data-id='ContactId']").removeAttribute("onchange");
            parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='ContactId']").parentNode.children[2]);
        }
        function queryContactName() {
            let sfId = document.getElementById(document.querySelector("[data-id='ContactId']").id + '_lkid').value;
            let contactsInfo = JSON.parse('{!contactsInfo}');
            let dataId = contactsInfo[sfId];
            // let queryContactBack = function(data){
            //     //To Do later
            //     console.log('ContactData = ' + data.object);
            //     document.querySelector("[data-id='ContactId']").value = data.object.lastName;
            // }
            // AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
            let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
            fetch(url, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then((result) => {
                document.querySelector("[data-id='ContactId']").value = result.object.lastName;
            })
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="CIC" class="pageTitleIcon" title="CIC" />
                <h1 class="pageType">CIC编辑
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> 新建CIC</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target=cases_edit.htm&amp;section=Cases&amp;language=zh_CN&amp;release=234.18.14&amp;instance=CS58&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:inputHidden value="{!contactId}" id="contactId"/>
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">CIC编辑</h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveCaseProcess('Save')" />
                                <input class="btn" type="Button" value="保存并关闭" onclick="saveCaseProcess('SaveAndClose')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveCaseProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <br/>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" showHeader="{!layoutSection.useHeader}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField html-data-id="{!layoutField.fieldAPI}" value="{!Case[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Case Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QueryCaseFromAWS();
                        unblockUI();
                    }
                    //Replace Vlookup Field
                    replaceSearchContactLookup();
                    //3. Set Readonly Attribute
                    document.querySelector("[data-id='OwnerId']").classList.add("disabledbutton");
                    document.querySelector("[data-id='RecordTypeId']").classList.add("disabledbutton");
                    //需要隐藏
                    // document.querySelector("[data-id='SuppliedEmail']").classList.add("displayblock");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButton" id="bottomButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveCaseProcess('Save')" />
                                <input class="btn" type="Button" value="保存并关闭" onclick="saveCaseProcess('SaveAndClose')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveCaseProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditCase.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditCase</label>
</ApexPage>
force-app/main/default/pages/NewAndEditContact.page
New file
@@ -0,0 +1,485 @@
<apex:page standardController="Contact" extensions="NewAndEditContactController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script>
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.medicalStaffFullName = leadPIData.lastName;// 完成field update workflow
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                if('{!rtTypeId}'){
                    payloadJson.RecordTypeId = '{!rtTypeId}';
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                               if(ele ){
                                   //_unselected
                                   let v = '';
                                   if(data.object[f]){
                                       v = data.object[f];
                                   }
                                   let arr = v.split(';');
                                   // 清空已有选项
                                   /*
                                   let sl = document.getElementById(ele.id + '_selected');
                                   if(sl){
                                       for(let op of sl.options){
                                           op.selected = true;
                                       }
                                       let la = document.getElementById(ele.id + '_left_arrow');
                                       if(la){
                                           la.click();
                                       }
                                   }
                                   // 赋值新选项
                                   let us = document.getElementById(ele.id + '_unselected');
                                   if(us){
                                       for(let op of us.options){
                                           op.selected = arr.indexOf(op.value)>-1;
                                       }
                                       let ra = document.getElementById(ele.id + '_right_arrow');
                                       if(ra){
                                           ra.click();
                                       }
                                   }*/
                                   for(let op of ele.options){
                                       op.selected = arr.indexOf(op.value)>-1;
                                   }
                                   let ra = document.getElementById(ele.id + '_right_arrow');
                                   if(ra){
                                       ra.click();
                                   }
                               }
                            }else{
                                ele.value = data.object[f];
                            }
                            if(ele.type.indexOf("select")>-1 && ele.value){
                                jQuery(ele).change()
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                // document.querySelector("[data-id='Phone']").value = data.object.phone;
                // document.querySelector("[data-id='Email']").value = data.object.email;
            },
            updateMethod:"NewAndEditContactController.saveContact",
            insertMethod:"NewAndEditContactController.saveContact"
        }
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormTag(tag_name){
            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
        }
        function IsFormElement(e){
            return IsFormTag(e.tagName);
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='Phone']";
            //Email
            let email = document.querySelector(textEmail);
            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
                error_msg += ';邮件格式错误';
            }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            //api_id_map
//let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index in api_id_map) {
                let ele = document.getElementById(api_id_map[index]);
                let field_api_name = index;
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormTag(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets;
                } else {
                    result[field_api_name] = ele.value;
                }
                // let e1 = document.getElementById(api_id_map[field_api_name]);
                // if(!result[field_api_name] && e1 && e1.value){
                //     result[field_api_name] = e1.value;
                // }
            }
            return result;
        }
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
            unblockUI();
        };
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. lead to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Contact[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                                         required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
            var init_nodes = document.getElementsByClassName("PIBackApi");
            var api_id_map={};
            for(let e of init_nodes){
                if(IsFormElement(e)){
                    if(e.getAttribute("multiple") != 'multiple' || e.style.display == 'none' && e.id.indexOf('selected') < 0){
                        api_id_map[GetEleApiName(e)] = e.id;
                    }
                }
            }
            console.log(api_id_map);
            sfdcPage.appendToOnloadQueue(function () {
                //1. Set Last Name label
                //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                //2. Query AWS Data by dataId
                console.log('Mode for Sobject Page:' + {!isNewMode});
                if (!{!isNewMode}) {
                    blockme();
                    QuerySobjectFromAWS();
                }
            });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditContact.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditContact</label>
</ApexPage>
force-app/main/default/pages/NewAndEditInquiryForm.page
New file
@@ -0,0 +1,607 @@
<apex:page standardController="Inquiry_form__c" extensions="NewAndEditInquiryFormController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        //配置方法
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let ele = GetEleByClass(config.ApiPrefix + "_"+ config.AWSToSobjectNonEncryptedMap[f]);
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                               if(ele && data.object[f]){
                                   let arr = data.object[f].split(';');
                                   // 给隐藏的select赋值
                                   for(let op of ele.options){
                                       op.selected = arr.indexOf(op.value)>-1;
                                   }
                                   // 利用按钮给显示的select赋值
                                   let ra = document.getElementById(ele.id + '_right_arrow');
                                   if(ra){
                                       ra.click();
                                   }
                               }
                            }else{
                                ele.value = data.object[f];
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                // document.querySelector("[data-id='Phone']").value = data.object.phone;
                // document.querySelector("[data-id='Email']").value = data.object.email;
            },
            updateMethod:"NewAndEditInquiryFormController.saveInquiryForm",
            insertMethod:"NewAndEditInquiryFormController.saveInquiryForm"
        }
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var staticResources = JSON.parse('{!staticResource}');
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        var staticResourcesLead = JSON.parse('{!staticResourceLead}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormElement(tag_name){
            return ['input','select','textarea'].indexOf(tag_name)>-1;
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            let textEmail = "[data-id='Email__c']";
            let textPhone = "[data-id='Phone__c']";
            if (document.querySelector("[data-id='Email__c']").value != "" && document.querySelector("[data-id='Email__c']").value != null) {
                //Email
                let email = document.querySelector(textEmail);
                if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
                    error_msg += ';邮件格式错误';
                }
            }
            if (document.querySelector("[data-id='Phone__c']").value != "" && document.querySelector("[data-id='Phone__c']").value != null) {
                let phone = document.querySelector(textPhone);
                if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                    error_msg += ';电话号码错误';
                }
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                let ele = nodelist[index];
                let field_api_name = GetEleApiName(ele);
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormElement(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name '+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    let targets = "";
                    //InquiryForm特殊处理
                    if(multiple == "Product1__c" || multiple == "Request1__c"){
                        targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[2].rows[1].cells[2].innerText;
                    }else{
                        targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    }
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets;
                } else {
                    result[field_api_name] = ele.value;
                }
            }
            return result;
        }
        //查询 解密
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        //查询 返回
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
        };
        //新建/更改 返回
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        //更新 to AWS
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        //新建 to AWS
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        //必填字段
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        //按钮点击方法
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. Inquiry to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        var newSearchContactWindow = null;
        var contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        //自定义lookup查询
        function searchContact(contactNodeId){
            // errorMsg 隐藏
            if(document.getElementsByClassName("errorMsg").length > 0){
                document.getElementsByClassName("errorMsg")[0].style.display="none";
            }
            let accountValue = "";
            let suffixUrl = "";
            if (document.querySelector("[data-id='Hospital_Name__c']")) {
                let accountNodeId = document.querySelector("[data-id='Hospital_Name__c']").id + '_lkid';
                accountValue = document.getElementById(accountNodeId).value;
            }
            console.log(accountValue);
            if(accountValue !='000000000000000'){
                suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
            }else{
                suffixUrl = "?contactId="+contactNodeId;
            }
            let baseUrl = "/apex/SearchContactPage";
            let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
            newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
            if (window.focus) {
                newSearchContactWindow.focus();
            }
            return false;
        }
        //窗口关闭时发生
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page:form:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id='Contact_Name__c']").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id='Contact_Name__c']").value = contactInfo.Name;
        }
        //替换vlookup
        function replaceSearchContactLookup() {
            let lookUpNode = htmlToElement(contactHtmlString);
            console.log(lookUpNode);
            if (!{!isNewMode}) {
                //1. Query Contact from AWS by AWSDataId
                queryContactName()
            }
            let parentNode = document.querySelector("[data-id='Contact_Name__c']").parentNode;
            document.querySelector("[data-id='Contact_Name__c']").removeAttribute("onchange");
            parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Contact_Name__c']").parentNode.children[2]);
        }
        function queryContactName() {
            let sfId = document.getElementById(document.querySelector("[data-id='Contact_Name__c']").id + '_lkid').value;
            let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
            let dataId = contactsInfo[sfId];
            // let queryContactBack = function(data){
            //     //To Do later
            //     console.log('ContactData = ' + data.object);
            //     document.querySelector("[data-id='Contact_Name__c']").value = data.object.lastName;
            // }
            // AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
            let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
            fetch(url, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then((result) => {
                document.querySelector("[data-id='Contact_Name__c']").value = result.object.lastName;
            })
        }
        //For Lead Search
        var leadHtmlString = '<img src="/img/s.gif" onclick="searchLead(\'page:form:leadId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
        var newSearchLeadWindow = null;
        //窗口关闭时发生
        function closeLeadPopupWindow() {
            if (null != newSearchLeadWindow) {
                newSearchLeadWindow.close();
            }
            let leadInfoStr = document.getElementById('page:form:leadId').value;
            console.log('closePopup:'+leadInfoStr);
            let leadInfo = JSON.parse(leadInfoStr);
            let leadNodeId = document.querySelector("[data-id='Lead_link__c']").id + '_lkid';
            document.getElementById(leadNodeId).value = leadInfo.LeadId;
            document.querySelector("[data-id='Lead_link__c']").value = leadInfo.Name;
        }
        function searchLead(leadNodeId){
            // let accountValue = "";
            // let suffixUrl = "";
            let suffixUrl = "?leadId="+leadNodeId;
            let baseUrl = "/apex/SearchLeadPage";
            let newSearchLeadParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
            newSearchLeadWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchLeadParam);
            if (window.focus) {
                newSearchLeadWindow.focus();
            }
            return false;
        }
        //替换查找Lead
        function replaceSearchLeadLookup() {
            let lookUpNode = htmlToElement(leadHtmlString);
            console.log(lookUpNode);
            if (!{!isNewMode}) {
                //1. Query Lead from AWS by AWSDataId
                queryLeadName()
            }
            let parentNode = document.querySelector("[data-id='Lead_link__c']").parentNode;
            document.querySelector("[data-id='Lead_link__c']").removeAttribute("onchange");
            parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Lead_link__c']").parentNode.children[2]);
        }
        function queryLeadName() {
            let sfId = document.getElementById(document.querySelector("[data-id='Lead_link__c']").id + '_lkid').value;
            let leadsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
            let dataId = leadsInfo[sfId];
            // let queryLeadBack = function(data){
            //     //To Do later
            //     console.log('ContactData = ' + data.object);
            //     document.querySelector("[data-id='Lead_link__c']").value = data.object.lastName;
            // }
            // AWSService.query(staticResourcesLead.queryUrl, dataId, queryLeadBack, staticResources.token);
            let url = staticResourcesLead.queryUrl + '?dataId=' + dataId;
            fetch(url, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then((result) => {
                document.querySelector("[data-id='Lead_link__c']").value = result.object.lastName;
            })
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:inputHidden value="{!contactId}" id="contactId"/>
        <apex:inputHidden value="{!leadId}" id="leadId"/>
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Inquiry_form__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Sobject Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QuerySobjectFromAWS();
                        unblockUI();
                    }
                    //Replace Contact Vlookup Field
                    replaceSearchContactLookup();
                    //Replace Lead Vlookup Field
                    replaceSearchLeadLookup();
                    document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
                    document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditInquiryForm.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditInquiryForm</label>
</ApexPage>
force-app/main/default/pages/NewAndEditInspectionReport.page
New file
@@ -0,0 +1,436 @@
<apex:page standardController="Inspection_Report__c" extensions="NewAndEditInspectionReportController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script>
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let ele = GetEleByClass(config.ApiPrefix + "_"+ config.AWSToSobjectNonEncryptedMap[f]);
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                               if(ele && data.object[f]){
                                   let arr = data.object[f].split(';');
                                   // 给隐藏的select赋值
                                   for(let op of ele.options){
                                       op.selected = arr.indexOf(op.value)>-1;
                                   }
                                   // 利用按钮给显示的select赋值
                                   let ra = document.getElementById(ele.id + '_right_arrow');
                                   if(ra){
                                       ra.click();
                                   }
                               }
                            }else{
                                ele.value = data.object[f];
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
                //document.querySelector("[data-id='Responsible_Person__c']").value = data.object.responsiblePersonHP;
                //document.querySelector("[data-id='phone__c']").value = data.object.callerPhone;
                //document.querySelector("[data-id='Email']").value = data.object.email;
            },
            updateMethod:"NewAndEditInspectionReportController.saveInspectionReport",
            insertMethod:"NewAndEditInspectionReportController.saveInspectionReport"
        }
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormElement(tag_name){
            return ['input','select','textarea'].indexOf(tag_name)>-1;
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='Phone']";
            //Email
            let email = document.querySelector(textEmail);
            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
                error_msg += ';邮件格式错误';
            }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                let ele = nodelist[index];
                console.log('ele:'+ele)
                let field_api_name = GetEleApiName(ele);
                console.log('field_api_name:'+field_api_name)
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormElement(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets;
                } else {
                    result[field_api_name] = ele.value;
                }
            }
            //let reporter = GetEleApiName(nodelist[5])
            //console.log('reporter:'+reporter);
            result['Reporter__c'] = document.getElementById('page:form:block:j_id50:0:j_id51:j_id52:4:j_id53_lkid').value;
            return result;
        }
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
            unblockUI();
        };
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            console.log('sobjJson:'+sobjJson);
            console.log('check:'+checkRequiredFieldMsgResult);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. lead to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Inspection_Report__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Sobject Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QuerySobjectFromAWS();
                    }
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditInspectionReport.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditInspectionReport</label>
</ApexPage>
force-app/main/default/pages/NewAndEditQIS.page
New file
@@ -0,0 +1,558 @@
<apex:page standardController="QIS_Report__c" extensions="NewAndEditQISController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script>
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectNonEncryptedMapKeySet:{!AWSToSobjectNonEncryptedMapKeySet},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.medicalStaffFullName = leadPIData.lastName;// 完成field update workflow
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f of config.AWSToSobjectNonEncryptedMapKeySet){
                        let ele = document.getElementById(api_id_map[config.AWSToSobjectNonEncryptedMap[f]])
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                               if(ele && data.object[f]){
                                   let arr = data.object[f].split(';');
                                   // 给隐藏的select赋值
                                   for(let op of ele.options){
                                       op.selected = arr.indexOf(op.value)>-1;
                                   }
                                   // 利用按钮给显示的select赋值
                                   let ra = document.getElementById(ele.id + '_right_arrow');
                                   if(ra){
                                       ra.click();
                                   }
                               }
                            }else{
                                ele.value = data.object[f];
                            }
                            if(ele.type.indexOf("select")>-1 && ele.value){
                                jQuery(ele).change()
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                // document.querySelector("[data-id='Phone']").value = data.object.phone;
                // document.querySelector("[data-id='Email']").value = data.object.email;
            },
            updateMethod:"NewAndEditQISController.saveQISReport",
            insertMethod:"NewAndEditQISController.saveQISReport"
        }
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormTag(tag_name){
            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
        }
        function IsFormElement(e){
            return IsFormTag(e.tagName);
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            //let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='Caller_phone__c']";
            //Email
            // let email = document.querySelector(textEmail);
            // if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
            //     error_msg += ';邮件格式错误';
            // }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            //api_id_map
//let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index in api_id_map) {
                let ele = document.getElementById(api_id_map[index]);
                let field_api_name = index;
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormTag(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets;
                } else {
                    result[field_api_name] = ele.value;
                }
                // let e1 = document.getElementById(api_id_map[field_api_name]);
                // if(!result[field_api_name] && e1 && e1.value){
                //     result[field_api_name] = e1.value;
                // }
            }
            //赋值富文本区域
            //问题内容描述(图片)-FSE-OCSM-OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:4:j_id51:j_id52:15:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.problem_detail_photo__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:4:j_id51:j_id52:15:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //问题内容描述(图片)-OSH回答完毕-现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:5:j_id51:j_id52:15:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.problem_detail_photo__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:5:j_id51:j_id52:15:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片1 - OCSM-现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:14:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_1__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:14:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片2-OCSM-现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:14:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_2__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:14:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片3 -OCSM-现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:14:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_3__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:14:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片4 -OCSM-现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:14:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_4__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:14:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH1 - OCSM
             if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:19:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_1__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:19:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH2-OCSM
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:19:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_2__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:19:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH3 -OCSM
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:19:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_3__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:19:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH4 -OCSM
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:19:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_4__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:19:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH1 - OSH回答完毕
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:18:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_1__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:18:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH2-OSH回答完毕
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:18:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_2__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:18:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH3 -OSH回答完毕
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:18:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_3__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:18:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH4 -OSH回答完毕
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:18:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_4__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:18:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片1 - OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:13:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_1__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:13:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片2-OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:13:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_2__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:13:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片3 -OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:13:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_3__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:13:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片4 -OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:13:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_4__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:13:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH1 - OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:16:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_1__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:16:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH2-OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:16:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_2__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:16:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH3 -OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:16:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_3__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:16:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH4 -OSH
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:16:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_4__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:16:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH1 -现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:17:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_1__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:17:j_id51:j_id52:0:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH2-现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:17:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_2__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:17:j_id51:j_id52:1:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH3 -现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:17:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_3__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:17:j_id51:j_id52:2:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片OSH4 -现场结案-final
            if(document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:17:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']")){
                result.Photo_OSH_4__c = document.querySelector("[title = 'RTF 編輯器, page:form:block:j_id50:17:j_id51:j_id52:3:j_id53:textAreaDelegate_problem_detail_photo__c']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            return result;
        }
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
            unblockUI();
        };
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. lead to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!QIS_Report__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                                         required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
            var init_nodes = document.getElementsByClassName("PIBackApi");
            var api_id_map={};
            for(let e of init_nodes){
                if(IsFormElement(e)){
                     api_id_map[GetEleApiName(e)] = e.id;
                }
            }
            console.log(api_id_map);
            sfdcPage.appendToOnloadQueue(function () {
                //1. Set Last Name label
                //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                //2. Query AWS Data by dataId
                console.log('Mode for Sobject Page:' + {!isNewMode});
                if (!{!isNewMode}) {
                    blockme();
                    QuerySobjectFromAWS();
                }
            });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditQIS.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditQIS</label>
</ApexPage>
force-app/main/default/pages/NewAndEditRepairSubOrder.page
New file
@@ -0,0 +1,575 @@
<apex:page standardController="RepairSubOrder__c" extensions="NewAndEditRepairSubOrderController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let ele = GetEleByClass(config.ApiPrefix + "_"+ config.AWSToSobjectNonEncryptedMap[f]);
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                               if(ele && data.object[f]){
                                   let arr = data.object[f].split(';');
                                   // 给隐藏的select赋值
                                   for(let op of ele.options){
                                       op.selected = arr.indexOf(op.value)>-1;
                                   }
                                   // 利用按钮给显示的select赋值
                                   let ra = document.getElementById(ele.id + '_right_arrow');
                                   if(ra){
                                       ra.click();
                                   }
                               }
                            }else{
                                ele.value = data.object[f];
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                // document.querySelector("[data-id='Phone']").value = data.object.phone;
                // document.querySelector("[data-id='Email']").value = data.object.email;
            },
            updateMethod:"NewAndEditRepairSubOrderController.saveRepairSubOrder",
            insertMethod:"NewAndEditRepairSubOrderController.saveRepairSubOrder"
        }
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormTag(tag_name){
            return ['input','select','textarea'].indexOf(tag_name.toLowerCase())>-1;
        }
        function IsFormElement(tag_name){
            return ['input','select','textarea'].indexOf(tag_name)>-1;
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            // let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='RepairApplicantTel__c']";
            //Email
            // let email = document.querySelector(textEmail);
            // if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
            //     error_msg += ';邮件格式错误';
            // }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                let ele = nodelist[index];
                let field_api_name = GetEleApiName(ele);
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormElement(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets;
                } else {
                    result[field_api_name] = ele.value;
                }
            }
            return result;
        }
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
            unblockUI();
        };
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. RepairSubOrder to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        //替换vlookup
        var newSearchContactWindow = null;
        var closeField = '';
        function replaceSearchContactLookup() {
            if (!{!isNewMode}) {
                //1. Query Contact from AWS by AWSDataId
                queryContactName()
            }
            if(document.querySelector("[data-id='Receiver__c']") != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Receiver__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                console.log(lookUpNode);
                let parentNode = document.querySelector("[data-id='Receiver__c']").parentNode;
                document.querySelector("[data-id='Receiver__c']").removeAttribute("onchange");
                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Receiver__c']").parentNode.children[2]);
            }
            if(document.querySelector("[data-id='Applicanter__c']") != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Applicanter__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                console.log(lookUpNode);
                let parentNode = document.querySelector("[data-id='Applicanter__c']").parentNode;
                document.querySelector("[data-id='Applicanter__c']").removeAttribute("onchange");
                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Applicanter__c']").parentNode.children[2]);
            }
        }
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        function queryContactName() {
            let contactsInfo = JSON.parse('{!LookUpOverrideFieldsMapJson}');
            if(document.querySelector("[data-id='Receiver__c']") != null){
                let sfId = document.getElementById(document.querySelector("[data-id='Receiver__c']").id + '_lkid').value;
                let dataId = contactsInfo[sfId];
                queryContactNameFetch(dataId, 'Receiver__c');
            }
            if(document.querySelector("[data-id='Applicanter__c']") != null){
                let sfId = document.getElementById(document.querySelector("[data-id='Applicanter__c']").id + '_lkid').value;
                let dataId = contactsInfo[sfId];
                queryContactNameFetch(dataId, 'Applicanter__c');
            }
        }
        function queryContactNameFetch(dataId, filedId){
            let queryContactBack = function(data){
                //To Do later
                console.log('ContactData = ' + data.object);
                document.querySelector("[data-id="+filedId+"]").value = data.object.lastName;
            }
            AWSService.query(staticResourcesContact.queryUrl, dataId, queryContactBack, staticResources.token);
        //     fetch(url, {
        //         method: 'GET',
        //         headers: {
        //             'Content-Type': 'application/json',
        //             'pi-token': staticResources.token
        //         }
        //     }).then((data) => {
        //         return data.json();
        //     }).then((result) => {
        //         if(result.object){
        //             document.querySelector("[data-id="+filedId+"]").value = result.object.lastName;
        //         }
        //     })
        }
        //自定义lookup查询
        function searchContact(contactNodeId,field){
            closeField = field;
            let accountValue = "";
            if (document.querySelector("[data-id='Department__c']")) {
                let accountNodeId = document.querySelector("[data-id='Department__c']").id + '_lkid';
                accountValue = document.getElementById(accountNodeId).value;
            }
            console.log('accountValue = ' + accountValue);
            if(accountValue !='000000000000000'){
                suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
            }else{
                suffixUrl = "?contactId="+contactNodeId;
            }
            let baseUrl = "/apex/SearchContactPage";
            let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
            newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
            if (window.focus) {
                newSearchContactWindow.focus();
            }
            return false;
            // if(true || accountValue !='000000000000000'){
            //     let baseUrl = "/apex/SearchContactPage";
            //     let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
            //     let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
            //     newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
            //     if (window.focus) {
            //         newSearchContactWindow.focus();
            //     }
            //     return false;
            // }else{
            //     alertErrorMessage('请先选择科室!');
            // }
        }
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page:form:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id="+closeField+"]").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id="+closeField+"]").value = contactInfo.Name;
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:inputHidden value="{!contactId}" id="contactId"/>
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!RepairSubOrder__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                var init_nodes = document.getElementsByClassName("PIBackApi");
                var api_id_map={};
                for(let e of init_nodes){
                    if(IsFormElement(e)){
                         api_id_map[GetEleApiName(e)] = e.id;
                    }
                }
                console.log(api_id_map);
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Sobject Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QuerySobjectFromAWS();
                    }
                    //Replace Vlookup Field
                    replaceSearchContactLookup();
                    //3. Set Readonly Attribute
                    document.querySelectorAll("[data-id='OwnerId']")[0].classList.add("disabledbutton");
                    document.querySelectorAll("[data-id='OwnerId']")[1].classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditRepairSubOrder.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditRepairSubOrder</label>
</ApexPage>
force-app/main/default/pages/NewAndEditReport.page
New file
@@ -0,0 +1,590 @@
<apex:page standardController="Report__c" extensions="NewAndEditReportController" id="page">
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        var redirectMode = 'Save';//1. Save 2. SaveAndNew
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var VLookUpFields = new Set(['Hospital_Reference__c', 'Department_Class_Ref__c', 'Daily_Report__c', 'OwnerId','Hospital_Department__c',
        'Competition_Company_Name__c','Report_OPDPlan__c','Loaner_request_no1__c','Practitioner1__c','Practitioner2__c','Practitioner3__c','Practitioner4__c',
        'Practitioner5__c','Opportunity1__c',
        'Opportunity2__c','Product01__c','Product1__c','Product2__c','Product3__c','Product4__c','Product5__c','Order_No__c','Person_In_Charge__c']);
        var closeField = '';
        // var myCkeditor = null;
        // try {
        //     myCkeditor = CKEDITOR;
        // } catch (error) {
        //     console.log('没有CKEDITOR')
        // }
        //错误提示
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:j_id5:msgContent");
            errorMsg = '错误:无效数据。'+'\n' + errorMsg;
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
            unblockUI();
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:j_id5:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        //1。获取所有字段值
        function getReportInformation() {
            let nodelist = document.querySelectorAll("[data-id]");
            let result = {}
            result.RecordTypeId = '{!rtTypeId}';
            for (let index = 0; index < nodelist.length; index++) {
                if (VLookUpFields.has(nodelist[index].getAttribute("data-id"))) {
                    console.log(nodelist[index].id.indexOf('lkwgt'));
                    if (nodelist[index].id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = nodelist[index].id + '_lkid';
                        let vlookUpNodeValue = document.getElementById(vlookUpNodeId).value;
                        result[nodelist[index].getAttribute("data-id")] = vlookUpNodeValue;
                    }
                } else if (nodelist[index].type == 'checkbox') {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].checked;
                } else if (nodelist[index].type == 'select-multiple') {
                    //nodelist[index].getAttribute("data-id")
                    let multiple = nodelist[index].getAttribute("data-id");
                    let targets = document.querySelector("[data-id=" + multiple + "]").nextSibling.children[0].children[1].children[2].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[nodelist[index].getAttribute("data-id")] = targets;
                } else {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].value;
                }
                let x = index + 1;
                if (x <= nodelist.length - 1 && (nodelist[x].getAttribute("data-id") == nodelist[index].getAttribute("data-id"))) {
                    index++;
                }
            }
            //手术分类1
            result.Technical_Category1__c = document.getElementById('page:form:j_id30:j_id60:4:j_id61:j_id62:2:j_id63')!=null?document.getElementById('page:form:j_id30:j_id60:4:j_id61:j_id62:2:j_id63').value:'';
            //手术分类2
            result.Technical_Category2__c = document.getElementById('page:form:j_id30:j_id60:4:j_id61:j_id62:4:j_id63')!=null?document.getElementById('page:form:j_id30:j_id60:4:j_id61:j_id62:4:j_id63').value:'';
            //目的2
            if(document.getElementById('page:form:j_id30:j_id60:3:j_id61:j_id62:1:j_id63')){
                result.Purpose2__c = document.getElementById('page:form:j_id30:j_id60:3:j_id61:j_id62:1:j_id63').value;
            }
            if(document.getElementById('page:form:j_id30:j_id60:2:j_id61:j_id62:1:j_id63')){
                result.Purpose2__c = document.getElementById('page:form:j_id30:j_id60:2:j_id61:j_id62:1:j_id63').value;
            }
            //富文本框赋值
            //用户签字的照片
            if(document.querySelector("[aria-describedby = 'cke_34']")){
                result.Customer_sigh_photo__c = document.querySelector("[aria-describedby = 'cke_34']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片1 Photo1__c
            if(document.querySelector("[aria-describedby = 'cke_42']")){
                result.Photo1__c = document.querySelector("[aria-describedby = 'cke_42']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片2 Photo2__c
            if(document.querySelector("[aria-describedby = 'cke_75']")){
                result.Photo2__c = document.querySelector("[aria-describedby = 'cke_75']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //照片3 Photo3__c
            if(document.querySelector("[aria-describedby = 'cke_108']")){
                result.Photo3__c = document.querySelector("[aria-describedby = 'cke_108']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //对应结果 VOC_follow_up_result__c cke_38
            if(document.querySelector("[aria-describedby = 'cke_38']")){
                result.VOC_follow_up_result__c = document.querySelector("[aria-describedby = 'cke_38']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            //对应结果第一次     VOC_follow_up_result1__c cke_71
            if(document.querySelector("[aria-describedby = 'cke_71']")){
                result.VOC_follow_up_result1__c = document.querySelector("[aria-describedby = 'cke_71']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            return result;
        }
        //2.验证规则
        function validateFieldValueFormate() {
            //VOC_Informer_Contact__c,Caller_phone_c__c
            let error_msg = '';
            let textEmail = "[data-id='    Follow_staff_email__c']";
            let textPhone1 = "[data-id='VOC_Informer_Contact__c']";
            let textPhone2 = "[data-id='Caller_phone_c__c']";
            //Email
            let email = document.querySelector(textEmail);
            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
                error_msg += ';对应者(邮箱)格式错误';
            }
            let phone1 = document.querySelector(textPhone1);
            if(phone1 && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone1.value)){
                error_msg += ';信息提供人联系方式(电话)号码错误';
            }
            let phone2 = document.querySelector(textPhone2);
            if(phone2 && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone2.value)){
                error_msg += ';联系电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        //3.验证必填字段
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        //4.获取要加密的字段
        function getPIPayload(reportJson) {
            let reportPayloadList = [];
            let reportPIData = new Object();
            reportPIData.vocInformerName = document.querySelector("[data-id='VOC_Informer_Name__c']")!=null?document.querySelector("[data-id='VOC_Informer_Name__c']").value:'';
            reportPIData.callerPhone = document.querySelector("[data-id='Caller_phone_c__c']")!=null?document.querySelector("[data-id='Caller_phone_c__c']").value:'';
            reportPIData.vocInformerContact = document.querySelector("[data-id='VOC_Informer_Contact__c']")!=null?document.querySelector("[data-id='VOC_Informer_Contact__c']").value:'';
            reportPIData.personInChargeText = document.querySelector("[data-id='Person_In_Charge_Text__c']")!=null?document.querySelector("[data-id='Person_In_Charge_Text__c']").value:'';
            reportPIData.professorSighText = document.querySelector("[data-id='Professor_sigh_text__c']")!=null?document.querySelector("[data-id='Professor_sigh_text__c']").value:'';
            reportPIData.staffInfoManual = document.querySelector("[data-id='Staff_Info_Manual_c__c']")!=null?document.querySelector("[data-id='Staff_Info_Manual_c__c']").value:'';
            reportPIData.responsiblePersonHP = document.querySelector("[data-id='Responsible_Person_HP_c__c']")!=null?document.querySelector("[data-id='Responsible_Person_HP_c__c']").value:'';
            reportPIData.practitioner1Part = document.querySelector("[data-id='Practitioner1_Part__c']")!=null?document.querySelector("[data-id='Practitioner1_Part__c']").value:'';
            reportPIData.practitioner2Part = document.querySelector("[data-id='Practitioner2_Part__c']")!=null?document.querySelector("[data-id='Practitioner2_Part__c']").value:'';
            reportPIData.practitioner3Part = document.querySelector("[data-id='Practitioner3_Part__c']")!=null?document.querySelector("[data-id='Practitioner3_Part__c']").value:'';
            reportPIData.practitioner4Part = document.querySelector("[data-id='Practitioner4_Part__c']")!=null?document.querySelector("[data-id='Practitioner4_Part__c']").value:'';
            reportPIData.practitioner5Part = document.querySelector("[data-id='Practitioner5_Part__c']")!=null?document.querySelector("[data-id='Practitioner5_Part__c']").value:'';
            reportPIData.age = document.querySelector("[data-id='age__c']")!=null?document.querySelector("[data-id='age__c']").value:'';
            reportPIData.medicalHistory = document.querySelector("[data-id='Medical_History__c']")!=null?document.querySelector("[data-id='Medical_History__c']").value:'';
            reportPIData.sex = document.querySelector("[data-id='sex__c']")!=null?document.querySelector("[data-id='sex__c']").value:'';
            reportPayloadList.push(reportPIData);
            return JSON.stringify(reportPayloadList);
        }
        //5.新建或编辑
        function ProcessPI(reportJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(reportJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(reportJson, payloadForNewPI)
            }
        }
        //新建
        function NewPIToAWS(reportJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewAndEditReportController.saveReport}';
            AWSService.insert(staticResources.newUrl, reportJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack, redirectCallBack);
        }
        //编辑
        function UpdatePIToAWS(reportJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewAndEditReportController.saveReport}';
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, reportJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        //查询
        function QueryLeadFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        var queryBack = function queryBack(data) {
            console.log('awsDataId = '+'{!AWSDataId}')
            console.log('data = ' + JSON.stringify(data));
            var i = 0;
            //赋值
            document.querySelector("[data-id='VOC_Informer_Name__c']")!=null?document.querySelector("[data-id='VOC_Informer_Name__c']").value=data.object.vocInformerName.replace(/"/g,""):i++;
            document.querySelector("[data-id='Caller_phone_c__c']")!=null?document.querySelector("[data-id='Caller_phone_c__c']").value=data.object.callerPhone.replace(/"/g,""):i++;
            document.querySelector("[data-id='VOC_Informer_Contact__c']")!=null?document.querySelector("[data-id='VOC_Informer_Contact__c']").value=data.object.vocInformerContact.replace(/"/g,""):i++;
            document.querySelector("[data-id='Person_In_Charge_Text__c']")!=null?document.querySelector("[data-id='Person_In_Charge_Text__c']").value=data.object.personInChargeText.replace(/"/g,""):i++;
            document.querySelector("[data-id='Professor_sigh_text__c']")!=null?document.querySelector("[data-id='Professor_sigh_text__c']").value=data.object.professorSighText.replace(/"/g,""):i++;
            document.querySelector("[data-id='Staff_Info_Manual_c__c']")!=null?document.querySelector("[data-id='Staff_Info_Manual_c__c']").value=data.object.staffInfoManual.replace(/"/g,""):i++;
            document.querySelector("[data-id='Responsible_Person_HP_c__c']")!=null?document.querySelector("[data-id='Responsible_Person_HP_c__c']").value=data.object.responsiblePersonHP.replace(/"/g,""):i++;
            document.querySelector("[data-id='Practitioner1_Part__c']")!=null?document.querySelector("[data-id='Practitioner1_Part__c']").value=data.object.practitioner1Part.replace(/"/g,""):i++;
            document.querySelector("[data-id='Practitioner2_Part__c']")!=null?document.querySelector("[data-id='Practitioner2_Part__c']").value=data.object.practitioner2Part.replace(/"/g,""):i++;
            document.querySelector("[data-id='Practitioner3_Part__c']")!=null?document.querySelector("[data-id='Practitioner3_Part__c']").value=data.object.practitioner3Part.replace(/"/g,""):i++;
            document.querySelector("[data-id='Practitioner4_Part__c']")!=null?document.querySelector("[data-id='Practitioner4_Part__c']").value=data.object.practitioner4Part.replace(/"/g,""):i++;
            document.querySelector("[data-id='Practitioner5_Part__c']")!=null?document.querySelector("[data-id='Practitioner5_Part__c']").value=data.object.practitioner5Part.replace(/"/g,""):i++;
            document.querySelector("[data-id='age__c']")!=null?document.querySelector("[data-id='age__c']").value=data.object.age.replace(/"/g,""):i++;
            document.querySelector("[data-id='Medical_History__c']")!=null?document.querySelector("[data-id='Medical_History__c']").value=data.object.medicalHistory.replace(/"/g,""):i++;
            document.querySelector("[data-id='sex__c']")!=null?document.querySelector("[data-id='sex__c']").value=data.object.sex.replace(/"/g,""):i++;
        };
        //替换vlookup
        function replaceSearchContactLookup() {
            if (!{!isNewMode}) {
                queryContactName();
            }
            if(document.querySelector("[data-id='Practitioner1__c']") != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Practitioner1__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                let parentNode = document.querySelector("[data-id='Practitioner1__c']").parentNode;
                document.querySelector("[data-id='Practitioner1__c']").removeAttribute("onchange");
                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Practitioner1__c']").parentNode.children[2]);
            }
            if(document.querySelector("[data-id='Practitioner2__c']") != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Practitioner2__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                let parentNode = document.querySelector("[data-id='Practitioner2__c']").parentNode;
                document.querySelector("[data-id='Practitioner2__c']").removeAttribute("onchange");
                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Practitioner2__c']").parentNode.children[2]);
            }
            if(document.querySelector("[data-id='Practitioner3__c']") != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Practitioner3__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                let parentNode = document.querySelector("[data-id='Practitioner3__c']").parentNode;
                document.querySelector("[data-id='Practitioner3__c']").removeAttribute("onchange");
                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Practitioner3__c']").parentNode.children[2]);
            }
            if(document.querySelector("[data-id='Practitioner4__c']") != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Practitioner4__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                let parentNode = document.querySelector("[data-id='Practitioner4__c']").parentNode;
                document.querySelector("[data-id='Practitioner4__c']").removeAttribute("onchange");
                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Practitioner4__c']").parentNode.children[2]);
            }
            if(document.querySelector("[data-id='Practitioner5__c']") != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Practitioner5__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                let parentNode = document.querySelector("[data-id='Practitioner5__c']").parentNode;
                document.querySelector("[data-id='Practitioner5__c']").removeAttribute("onchange");
                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Practitioner5__c']").parentNode.children[2]);
            }
            if(document.querySelector("[data-id='Person_In_Charge__c']") != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\',\'Person_In_Charge__c\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                let parentNode = document.querySelector("[data-id='Person_In_Charge__c']").parentNode;
                document.querySelector("[data-id='Person_In_Charge__c']").removeAttribute("onchange");
                parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Person_In_Charge__c']").parentNode.children[2]);
            }
        }
        var newSearchContactWindow = null;
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        function queryContactName() {
            let contactsInfo = JSON.parse('{!contactsInfo}');
            if(document.querySelector("[data-id='Practitioner1__c']") != null){
                let sfId = document.getElementById(document.querySelector("[data-id='Practitioner1__c']").id + '_lkid').value;
                let dataId = contactsInfo[sfId];
                let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
                queryContactNameFetch(url,'Practitioner1__c');
            }
            if(document.querySelector("[data-id='Practitioner2__c']") != null){
                let sfId = document.getElementById(document.querySelector("[data-id='Practitioner2__c']").id + '_lkid').value;
                let dataId = contactsInfo[sfId];
                let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
                queryContactNameFetch(url,'Practitioner2__c');
            }
            if(document.querySelector("[data-id='Practitioner3__c']") != null){
                let sfId = document.getElementById(document.querySelector("[data-id='Practitioner3__c']").id + '_lkid').value;
                let dataId = contactsInfo[sfId];
                let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
                queryContactNameFetch(url,'Practitioner3__c');
            }
            if(document.querySelector("[data-id='Practitioner4__c']") != null){
                let sfId = document.getElementById(document.querySelector("[data-id='Practitioner4__c']").id + '_lkid').value;
                let dataId = contactsInfo[sfId];
                let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
                queryContactNameFetch(url,'Practitioner4__c');
            }
            if(document.querySelector("[data-id='Practitioner5__c']") != null){
                let sfId = document.getElementById(document.querySelector("[data-id='Practitioner5__c']").id + '_lkid').value;
                let dataId = contactsInfo[sfId];
                let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
                queryContactNameFetch(url,'Practitioner5__c');
            }
            if(document.querySelector("[data-id='Person_In_Charge__c']") != null){
                let sfId = document.getElementById(document.querySelector("[data-id='Person_In_Charge__c']").id + '_lkid').value;
                let dataId = contactsInfo[sfId];
                let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
                queryContactNameFetch(url,'Person_In_Charge__c');
            }
        }
        function queryContactNameFetch(url,filedId){
            fetch(url, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then((result) => {
                if(result.object){
                    document.querySelector("[data-id="+filedId+"]").value = result.object.lastName;
                }
            })
        }
        //自定义lookup查询
        function searchContact(contactNodeId,field){
            closeField = field;
            let accountValue = "";
            if (document.querySelector("[data-id='Hospital_Department__c']")) {
                let accountNodeId = document.querySelector("[data-id='Hospital_Department__c']").id + '_lkid';
                accountValue = document.getElementById(accountNodeId).value;
            }
            console.log(accountValue);
            if(accountValue !='000000000000000'){
                let baseUrl = "/apex/SearchContactPage";
                let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
                if (window.focus) {
                    newSearchContactWindow.focus();
                }
                return false;
            }else{
                alertErrorMessage('{!PIPL_Input_Account_Error_Msg}');
            }
        }
        //窗口关闭时发生
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page:form:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id="+closeField+"]").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id="+closeField+"]").value = contactInfo.Name;
        }
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        //新建编辑回调函数
        var insertOrUpdateBack = function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            console.log('Result from AWS' + result);
            console.log('payloadJson=' + payloadJson);
            payloadJson.VOC_Informer_Name__c = result.object[0].vocInformerName;
            payloadJson.Caller_phone_c__c = result.object[0].callerPhone;
            payloadJson.VOC_Informer_Contact__c = result.object[0].vocInformerContact;
            payloadJson.Person_In_Charge_Text__c = result.object[0].personInChargeText;
            payloadJson.Staff_Info_Manual_c__c = result.object[0].staffInfoManual;
            payloadJson.Responsible_Person_HP_c__c = result.object[0].responsiblePersonHP;
            payloadJson.Professor_sigh_text__c = result.object[0].professorSighText;
            payloadJson.Practitioner1_Part__c = result.object[0].practitioner1Part;
            payloadJson.Practitioner2_Part__c = result.object[0].practitioner2Part;
            payloadJson.Practitioner3_Part__c = result.object[0].practitioner3Part;
            payloadJson.Practitioner4_Part__c = result.object[0].practitioner4Part;
            payloadJson.Practitioner5_Part__c = result.object[0].practitioner5Part;
            payloadJson.age__c = result.object[0].age;
            payloadJson.Medical_History__c = result.object[0].medicalHistory;
            payloadJson.sex__c = result.object[0].sex;
            payloadJson.VOC_Informer_Name_Encrypted__c = result.object[0].vocInformerNameEncrypt;
            payloadJson.Caller_phone_c_Encrypted__c = result.object[0].callerPhoneEncrypt;
            payloadJson.VOC_Informer_Contact_Encrypted__c = result.object[0].vocInformerContactEncrypt;
            payloadJson.Person_In_Charge_Text_Encrypted__c = result.object[0].personInChargeTextEncrypt;
            payloadJson.Professor_sigh_text_Encrypted__c = result.object[0].professorSighTextEncrypt;
            payloadJson.Staff_Info_Manual_c_Encrypted__c = result.object[0].staffInfoManualEncrypt;
            payloadJson.Responsible_Person_HP_c_Encrypted__c = result.object[0].responsiblePersonHPEncrypt;
            payloadJson.Practitioner1_Part_Encrypted__c = result.object[0].practitioner1PartEncrypt;
            payloadJson.Practitioner2_Part_Encrypted__c = result.object[0].practitioner2PartEncrypt;
            payloadJson.Practitioner3_Part_Encrypted__c = result.object[0].practitioner3PartEncrypt;
            payloadJson.Practitioner4_Part_Encrypted__c = result.object[0].practitioner4PartEncrypt;
            payloadJson.Practitioner5_Part_Encrypted__c = result.object[0].practitioner5PartEncrypt;
            payloadJson.age_Encrypted__c = result.object[0].ageEncrypt;
            payloadJson.Medical_History_Encrypted__c = result.object[0].medicalHistoryEncrypt;
            payloadJson.sex_Encrypted__c = result.object[0].sexEncrypt;
            if (isNewMode) {
                payloadJson.AWS_Data_Id__c = result.object[0].dataId;
            } else {
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            }
            return payloadJson;
        }
        //跳转页面
        var redirectCallBack = function redirectCallBack(sfId,errorMessage) {
            if(sfId){
                if(redirectMode == 'Save'){
                    window.open('/' + sfId, '_self');
                }else if(redirectMode == 'SaveAndNew'){
                    window.open('/setup/ui/recordtypeselect.jsp?ent=' + '{!sobjectId}' + '&retURL=/' + '{!sobjectPrefix}' + '/o&save_new_url=/' + '{!sobjectPrefix}' + '/e?retURL=%2F' + '{!sobjectPrefix}' + '%2Fo', '_self');
                }
            }else{
                alertErrorMessage(errorMessage);
            }
        }
        //点击保存按钮
        function saveReportProcess(saveMode) {
            redirectMode = saveMode;
            console.log('redirectMode' + redirectMode);
            hiddenErrorMsgNode();
            //1. Get report Information from Form
            let reportJson = getReportInformation();
            //2. Validate the report field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // 3. Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(reportJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('{!requiredErrorMsg}'+checkRequiredFieldMsgResult);
                return
            }
            //4. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(reportJson);
            console.log('加密字段:'+payloadForNewPI);
            //5. report to AWS
            ProcessPI(reportJson, payloadForNewPI);
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="报告书" class="pageTitleIcon" title="报告书" />
                <h1 class="pageType">报告书
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> 新建报告书</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target=leads_edit.htm&amp;section=Leads&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:inputHidden value="{!contactId}" id="contactId" />
        <!-- Error Msg-->
        <!-- <apex:outputPanel id="errorMsg">
            <apex:pageMessages id="msgContent" escape="false" />
        </apex:outputPanel> -->
        <apex:pageblock >
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">报告书编辑</h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveReportProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveReportProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <br/>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" showHeader="{!layoutSection.useHeader}" collapsible="{!layoutSection.allowCollapse}"
                    columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField html-data-id="{!layoutField.fieldAPI}" styleClass="{!layoutField.fieldAPI}" value="{!Report__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Lead Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        QueryLeadFromAWS();
                    }
                    //Replace Vlookup Field
                    replaceSearchContactLookup();
                    //3. Set Readonly Attribute
                    document.querySelector("[data-id='OwnerId']").classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveReportProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveReportProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditReport.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditReport</label>
</ApexPage>
force-app/main/default/pages/NewAndEditTenderinformation.page
New file
@@ -0,0 +1,434 @@
<apex:page standardController="Tender_information__c" extensions="NewAndEditTenderinformationController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script>
        var config = {};
        config = {
            SobjectName : "{!SobjectName}",
            ApiPrefix:"{!ApiPrefix}",
            SaveAndNew:false,
            AWSToSobjectMap:{!AWSToSobjectMapJson},
            AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
            AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson},
            SobjectToAWSModel:function (sobjJson) {
                let leadPayloadList = [];
                let leadPIData = {};
                for(let f in config.AWSToSobjectMap){
                    if(sobjJson.hasOwnProperty(config.AWSToSobjectMap[f])){
                        leadPIData[f] = sobjJson[config.AWSToSobjectMap[f]]
                    }
                    else{
                        console.log(config.AWSToSobjectMap[f] + 'is not in sobjJson');
                    }
                }
                leadPIData.sfRecordId = '';
                console.log('Sobject PI Data:' + leadPIData);
                leadPayloadList.push(leadPIData);
                console.log(JSON.stringify(leadPayloadList));
                return JSON.stringify(leadPayloadList);
            },
            insertOrUpdateBack:function(payloadJson, r, isNewMode){
                for(let f in config.AWSToSobjectMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                for(let f in config.AWSToSobjectEncryptedMap){
                    if(r.object[0].hasOwnProperty(f)){
                        payloadJson[config.AWSToSobjectEncryptedMap[f]] = r.object[0][f];
                    }
                    else{
                        console.log(f + 'is not in r.object[0]');
                    }
                }
                //payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                if (isNewMode) {
                    payloadJson.AWS_Data_Id__c = r.object[0].dataId;
                } else {
                    payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
                }
                return payloadJson;
            },
            queryBack:function (data) {
                console.log('data = ' + data);
                if(data.object){
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let ele = GetEleByClass(config.ApiPrefix + "_"+ config.AWSToSobjectNonEncryptedMap[f]);
                        if(data.object.hasOwnProperty(f) && ele){
                            // 多选特殊处理
                            if(ele.type == 'select-multiple'){
                               //let me = GetEleByClass(config.ApiPrefix+'_'+field_api_name);
                               if(ele && data.object[f]){
                                   let arr = data.object[f].split(';');
                                   // 给隐藏的select赋值
                                   for(let op of ele.options){
                                       op.selected = arr.indexOf(op.value)>-1;
                                   }
                                   // 利用按钮给显示的select赋值
                                   let ra = document.getElementById(ele.id + '_right_arrow');
                                   if(ra){
                                       ra.click();
                                   }
                               }
                            }else{
                                ele.value = data.object[f];
                            }
                        }
                        else{
                            console.log(f + 'is not in data.object');
                        }
                    }
                }
                else{
                    console.log('data.object = ' + data.object);
                }
                // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                // document.querySelector("[data-id='Phone']").value = data.object.phone;
                // document.querySelector("[data-id='Email']").value = data.object.email;
            },
            updateMethod:"NewAndEditTenderinformationController.saveTenderinformation",
            insertMethod:"NewAndEditTenderinformationController.saveTenderinformation"
        }
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        console.log('{!staticResource}');
        var VLookUpFields = {! VLookUpFieldsJson};
        function ProcessPI(sobjJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode}) {
                NewPIToAWS(sobjJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(sobjJson, payloadForNewPI)
            }
        }
        var GetEleByClass = function(class_name){
            let eles = document.getElementsByClassName(class_name);
            if(eles.length > 0) return eles[0];
            return null;
        }
        var GetEleApiName = function(ele){
            for(let c of ele.classList){
                if(c.indexOf(config.ApiPrefix+'_')>-1){
                    return c.replace(config.ApiPrefix+'_','');
                }
            }
            return '';
        }
        function IsFormElement(tag_name){
            return ['input','select','textarea'].indexOf(tag_name)>-1;
        }
        function getPIPayload(sobjJson) {
            return config.SobjectToAWSModel(sobjJson);
        }
        function validateFieldValueFormate() {
            let error_msg = '';
            let textEmail = "[data-id='Email']";
            let textPhone = "[data-id='Phone']";
            //Email
            let email = document.querySelector(textEmail);
            if(email && !/^[\w-]{3,12}@[\da-zA-Z]{2,16}\.[a-zA-Z]+$/.test(email.value)){
                error_msg += ';邮件格式错误';
            }
            let phone = document.querySelector(textPhone);
            if(phone && !/^1[3|5|8|7][0-9]\d{4,8}$/.test(phone.value)){
                error_msg += ';电话号码错误';
            }
            for(let e of document.getElementsByTagName('select')){
                for(let op of e.options){
                    if(op.value == "*****" && op.selected){
                        error_msg += ';下拉框不能主动选择密文选项';
                    }
                }
            }
            if(error_msg.length>0 && error_msg[0]== ';'){
                error_msg = error_msg.substring(1);
            }
            return error_msg;
        }
        function getSobjectInformation() {
            let nodelist = document.getElementsByClassName(config.ApiPrefix);
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                let ele = nodelist[index];
                let field_api_name = GetEleApiName(ele);
                let tag_name = ele.tagName.toLowerCase();
                if(!IsFormElement(tag_name)){
                    console.log('tag_name='+tag_name+',field_api_name'+field_api_name+' is not a form element');
                    continue;
                }
                if (VLookUpFields.indexOf(field_api_name)>=0) {
                    console.log(ele.id.indexOf('lkwgt'));
                    if (ele.id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = ele.id + '_lkid';
                        let vlook_ele = document.getElementById(vlookUpNodeId);
                        let v = '';
                        if(vlook_ele){
                            v = vlook_ele.value;
                        }else{
                            v = ele.value;
                        }
                        if(v && v != "000000000000000"){
                            result[field_api_name] = v;
                        }
                    }
                } else if (ele.type == 'checkbox') {
                    result[field_api_name] = ele.checked;
                } else if (ele.type == 'select-multiple') {
                    //field_api_name
                    let multiple = field_api_name;
                    //let targets = GetEleByClass(config.ApiPrefix+'_'+field_api_name).parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    let targets = [];
                    for(let i = 0; i < ele.selectedOptions.length; i++) {
                        //let ele = nodelist[i];
                        //targets = targets.replace(ele.selectedOptions[i].value,";");
                        targets.push(ele.selectedOptions[i].value);
                    }
                    //targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[field_api_name] = targets.join(";");
                } else {
                    result[field_api_name] = ele.value;
                }
            }
            return result;
        }
        function QuerySobjectFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        function queryBack(data) {
            console.log('data = ' + data);
            config.queryBack(data);
            unblockUI();
        };
        function insertOrUpdateBack(payloadJson, result, isNewMode) {
            console.log(result);
            let r = result;
            console.log('Result from AWS' + r);
            console.log('payloadJson=' + payloadJson);
            return config.insertOrUpdateBack(payloadJson, r, isNewMode);
        }
        function redirectCallBack(sfId,errorMsg) {
            unblockUI();
            if(errorMsg){
                alertErrorMessage(errorMsg);
            }
            else{
                if(config.SaveAndNew){
                    window.open('{! SaveAndNewButtonUrl }','_self');
                }else{
                    window.open('/' + sfId, '_self');
                }
            }
        }
        function UpdatePIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.updateMethod;
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, sobjJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack,redirectCallBack);
        }
        function NewPIToAWS(sobjJson, payloadForNewPI) {
            let controllerSaveMethod = config.insertMethod;
            AWSService.insert(staticResources.newUrl, sobjJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack,redirectCallBack);
        }
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for(i = 0;i<requiredFieldAPIList.length;i++){
                if(formData[requiredFieldAPIList[i]]){
                    continue;
                }else{
                    if(blankRequiredFields == ''){
                        blankRequiredFields =blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }else{
                        blankRequiredFields =blankRequiredFields+',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        function saveSobjectProcess(save_and_new) {
            if(save_and_new){
                config.SaveAndNew = true;
            }
            hiddenErrorMsgNode();
            //1. Get Sobject Information from Form
            let sobjJson = getSobjectInformation();
            //2. Validate the Sobject field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage(validationResultMessage);
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(sobjJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('requiredErrorMsg' + checkRequiredFieldMsgResult);
                return
            }
            // //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(sobjJson);
            // //4. Get Authentication Information for AWS
            // loadAWSAuthentication();
            // //5. lead to AWS
            ProcessPI(sobjJson, payloadForNewPI);
            // awsToken = TestToken;
            // NewPIToAWS(sobjJson,awsToken, payloadForNewPI)
        }
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="{! SobjectLabel}" class="pageTitleIcon" title="{! SobjectLabel}" />
                <h1 class="pageType">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> <apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText>{! SobjectLabel}</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target={!sobjectTypeValue}s_edit.htm&amp;section={!sobjectTypeValue}s&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:pageblock id="block">
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">{! SobjectLabel}<apex:outputText rendered="{!isNewMode}">{!$Label.New}</apex:outputText><apex:outputText rendered="{!not(isNewMode)}">{!$Label.Edit}</apex:outputText></h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess(1)" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Error Msg-->
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField styleClass="{!ApiPrefix} {!ApiPrefix}_{!layoutField.fieldAPI}" html-data-id="{!layoutField.fieldAPI}" value="{!Tender_information__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                sfdcPage.appendToOnloadQueue(function () {
                    //1. Set Last Name label
                    //document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[2].children[0].innerText = '姓名';
                    //2. Query AWS Data by dataId
                    console.log('Mode for Sobject Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        bolckme();
                        QuerySobjectFromAWS();
                    }
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="{!$Label.Save}" onclick="saveSobjectProcess()" />
                                <input class="btn" type="Button" value="{!$Label.SaveAndNew}" onclick="saveSobjectProcess()" />
                                <apex:commandButton action="{!cancel}" value="{!$Label.Cancel}" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewAndEditTenderinformation.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewAndEditTenderinformation</label>
</ApexPage>
force-app/main/default/pages/NewConsumApply.page
New file
@@ -0,0 +1,402 @@
<apex:page standardController="Consum_Apply__c" extensions="NewConsumApplyController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        //Initial Required Information
        var staticResources = JSON.parse('{!staticResource}');
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var VLookUpFields = new Set(['Loaner_medical_Staff__c', 'Hospital__c', 'Strategic_dept__c', 'Account__c', 'QIS_number__c', 'OPDPlan__c', 'Campaign__c', 'Rental_Apply__c', 'Shipment_address__c', 'Dealer__c', 'Old_Consum_Apply__c', 'DeliverySlip__c', 'OwnerId', 'OPD__c']);
        var userVLookUpFields = ['Person_In_Charge__c', 'applyUser__c', 'CC_EmailUser__c', 'Assign_Person__c', 'Consum_Assistant__c', 'Consum_Assistant2__c', 'Consum_Assistant3__c', 'SalesManager__c', 'ZongjianApprovalManager__c', 'BuchangApprovalManagerSales__c', 'TongkuoZongjian__c'];
        var redirectMode = 'Save';
        //Redirect Required Parameter
        var redirectCallBack = function redirectCallBack(sfId,errorMessage) {
            if(sfId){
                if (redirectMode == 'Save') {
                window.open('/' + sfId, '_self');
            } else if (redirectMode == 'SaveAndNew') {
                window.open('/a3i/e', '_self');
            }
            }else{
                // alert(errorMessage);
                alertErrorMessage(errorMessage);
            }
        }
        //Query Required Parameter
        var queryBack = function queryBack(data) {
            console.log('data = ' + data);
            document.querySelector("[data-id='Phone_number__c']").value = data.object.phoneNumber;
            document.querySelector("[data-id='direct_shippment_address__c']").value = data.object.directShippmentAddress;
            unblockUI();
        };
        //Check If Insert Or Update
        var insertOrUpdateBack = function insertOrUpdateBack(payloadJson, result, isNewMode) {
            debugger
            console.log(result);
            let r = result;
            console.log('Result from AWS' + JSON.stringify(r));
            console.log('payloadJson=' + JSON.stringify(payloadJson));
            payloadJson.Phone_number__c = r.object[0].phoneNumber;
            payloadJson.direct_shippment_address__c = r.object[0].directShippmentAddress;
            payloadJson.Phone_Number_Encrypt__c = r.object[0].phoneNumberEncrypt;
            payloadJson.Direct_Shippment_Address_Encrypt__c = r.object[0].directShippmentAddressEncrypt;
            payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            if (isNewMode) {
                payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            } else {
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            }
            debugger
            return payloadJson;
        }
        // New Or Edit
        function ProcessPI(consumApplyJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode
            }) {
                NewPIToAWS(consumApplyJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(consumApplyJson, payloadForNewPI)
            }
        }
        //Get Sensitive Information
        function getPIPayload(consumApplyJson) {
            let consumApplyPayloadList = [];
            let phoneNumber = consumApplyJson.Phone_number__c;
            let directShippmentAddress = consumApplyJson.direct_shippment_address__c;
            let consumApplyPIData = new Object();
            consumApplyPIData.phoneNumber = phoneNumber;
            consumApplyPIData.directShippmentAddress = directShippmentAddress;
            consumApplyPIData.sfRecordId = '';
            console.log('consumApply PI Data:' + JSON.stringify(consumApplyPIData));
            consumApplyPayloadList.push(consumApplyPIData);
            console.log(JSON.stringify(consumApplyPayloadList));
            return JSON.stringify(consumApplyPayloadList);
        }
        //Check Validate Field Value
        function validateFieldValueFormate() {
            return true;
            // let textEmail = "[data-id='Loaner_centre_mail_address__c']";
            // let textPhone = "[data-id='Phone_number__c']";
            // //Email
            // let email = document.querySelector(textEmail).value;
            // let phone = document.querySelector(textPhone).value;
            // let regEmail = /^[\w-]{3,12}@[\da-zA-Z]{2,6}\.[a-zA-Z]+$/;
            // let regPhone = /^1[3|5|8|7][0-9]\d{4,8}$/;
            // let emailFormate = regEmail.test(email);
            // let phoneFormate = regPhone.test(phone);
            // console.log(emailFormate);
            // console.log(phoneFormate);
            // if (emailFormate == true && phoneFormate == true) {
            //     return true;
            // } else {
            //     return false;
            // }
        }
        //Get Page Information
        function getConsumApplyInformation() {
            let nodelist = document.querySelectorAll("[data-id]");
            let result = {}
            //富文本
            if(document.querySelector("[aria-describedby = 'cke_34']")){
                result.HP_received_sign_rich__c = document.querySelector("[aria-describedby = 'cke_34']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            for (let index = 0; index < nodelist.length; index++) {
                if (VLookUpFields.has(nodelist[index].getAttribute("data-id"))) {
                    console.log(nodelist[index].id.indexOf('lkwgt'));
                    if (nodelist[index].id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = nodelist[index].id + '_lkid';
                        let vlookUpNodeValue = document.getElementById(vlookUpNodeId).value;
                        result[nodelist[index].getAttribute("data-id")] = vlookUpNodeValue;
                    }
                } else if (nodelist[index].type == 'checkbox') {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].checked;
                } else if (nodelist[index].type == 'select-multiple') {
                    //nodelist[index].getAttribute("data-id")
                    let multiple = nodelist[index].getAttribute("data-id");
                    let targets = document.querySelector("[data-id=" + multiple + "]").parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[nodelist[index].getAttribute("data-id")] = targets;
                } else {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].value;
                }
                let x = index + 1;
                if (x <= nodelist.length - 1 && (nodelist[x].getAttribute("data-id") == nodelist[index].getAttribute("data-id"))) {
                    index++;
                }
            }
            for (let i = 0; i < userVLookUpFields.length; i++) {
                let userVlookUpNodeValue = document.querySelector("[data-id='" + userVLookUpFields[i] + "']").children[1].value;
                console.log('userVlookUpNodeValue:'+userVlookUpNodeValue);
                if(userVlookUpNodeValue!='000000000000000'){
                    result[userVLookUpFields[i]] = userVlookUpNodeValue;
                }
            }
            console.log(JSON.stringify(result));
            return result;
        }
        //Query from AWS
        function QueryConsumApplyFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        //Update Sensitive Information to AWS
        function UpdatePIToAWS(consumApplyJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewConsumApplyController.saveConsumApply}';
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, consumApplyJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack, redirectCallBack);
        }
        //Insert Sensitive Information to AWS
        function NewPIToAWS(consumApplyJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewConsumApplyController.saveConsumApply}';
            AWSService.insert(staticResources.newUrl, consumApplyJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack, redirectCallBack);
        }
        //Check Required Fields
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for (i = 0; i < requiredFieldAPIList.length; i++) {
                if (formData[requiredFieldAPIList[i]]) {
                    continue;
                } else {
                    if (blankRequiredFields == '') {
                        blankRequiredFields = blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    } else {
                        blankRequiredFields = blankRequiredFields + ',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        //Base Process
        function saveConsumApplyProcess(saveMode) {
            redirectMode = saveMode;
            console.log('redirectMode' + redirectMode);
            hiddenErrorMsgNode();
            //1. Get consumApply Information from Form
            let consumApplyJson = getConsumApplyInformation();
            //2. Validate the consumApply field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (!validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage('邮箱格式输入有误,请重新输入!');
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(consumApplyJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('{!Input_Required_Field_Msg}' + checkRequiredFieldMsgResult);
                return
            }
            //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(consumApplyJson);
            //4. consumApply to AWS
            ProcessPI(consumApplyJson, payloadForNewPI);
        }
        //Alert Error Message
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsg = '错误:无效数据。' + '\n' + errorMsg;
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
            unblockUI();
        }
        //Hide Error Message
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        //替换vlookup
        function replaceSearchContactLookup() {
            let lookUpNode = htmlToElement(contactHtmlString);
            console.log(lookUpNode);
            if (!{!isNewMode}) {
                queryContactName();
            }
            let parentNode = document.querySelector("[data-id='Loaner_medical_Staff__c']").parentNode;
            document.querySelector("[data-id='Loaner_medical_Staff__c']").removeAttribute("onchange");
            parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Loaner_medical_Staff__c']").parentNode.children[2]);
        }
        var newSearchContactWindow = null;
        var contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        function queryContactName() {
            let sfId = document.getElementById(document.querySelector("[data-id='Loaner_medical_Staff__c']").id + '_lkid').value;
            let contactsInfo = JSON.parse('{!contactsInfo}');
            let dataId = contactsInfo[sfId];
            let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
            fetch(url, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then((result) => {
                document.querySelector("[data-id='Loaner_medical_Staff__c']").value = result.object.lastName;
            })
        }
        //自定义lookup查询
        function searchContact(contactNodeId){
            let accountValue = "";
            if (document.querySelector("[data-id='Account__c']")) {
                let accountNodeId = document.querySelector("[data-id='Account__c']").id + '_lkid';
                accountValue = document.getElementById(accountNodeId).value;
            }
            console.log(accountValue);
            if(accountValue !='000000000000000'){
                let baseUrl = "/apex/SearchContactPage";
                let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
                if (window.focus) {
                    newSearchContactWindow.focus();
                }
                return false;
            }else{
                alertErrorMessage('{!PIPL_Input_Account_Error_Msg}');
            }
        }
        //窗口关闭时发生
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page:form:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id='Loaner_medical_Staff__c']").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id='Loaner_medical_Staff__c']").value = contactInfo.Name;
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="耗材备品申请" class="pageTitleIcon" title="耗材备品申请" />
                <h1 class="pageType">耗材备品申请编辑
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> 新建耗材备品申请</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target=consumApplys_edit.htm&amp;section=consumApplys&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:inputHidden value="{!contactId}" id="contactId"/>
        <!-- Error Msg-->
        <apex:outputPanel id="errorMsg">
            <apex:pageMessages id="msgContent" escape="false" />
        </apex:outputPanel>
        <apex:pageblock >
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">耗材备品申请编辑</h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveConsumApplyProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveConsumApplyProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField html-data-id="{!layoutField.fieldAPI}" value="{!Consum_Apply__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                //Append Page
                sfdcPage.appendToOnloadQueue(function () {
                    //2. Query AWS Data by dataId
                    console.log('Mode for consumApply Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QueryConsumApplyFromAWS();
                    };
                    //Replace Vlookup Field
                    replaceSearchContactLookup();
                    document.querySelector("[data-id='OwnerId']").classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveConsumApplyProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveConsumApplyProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewConsumApply.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewConsumApply</label>
</ApexPage>
force-app/main/default/pages/NewConsumApplyEquipmentSetDetail.page
New file
@@ -0,0 +1,300 @@
<apex:page standardController="Consum_Apply_Equipment_Set_Detail__c" extensions="NewConsumApplyEquipSetDetailController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        //Initial Required Information
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var VLookUpFields = new Set(['Consum_Apply__c','Consum_Apply_Equipment_Set__c','Asset__c','Canceled__c','DeliverySlip__c','Return_DeliverySlip__c']);
        var userVLookUpFields = ['Follower_User__c','Consum_Assign_Person__c','Asset_Center_Confirm_Staff__c','Return_Operator__c','Return_wh_chenk_staff__c','Cancel_Mem__c','Lost_item_check_staff__c','Lost_item_check_staff_Final__c'];
        var redirectMode = 'Save';
        //Redirect Required Parameter
        var redirectCallBack = function redirectCallBack(sfId, errorMessage) {
            if (sfId) {
                if (redirectMode == 'Save') {
                    window.open('/' + sfId, '_self');
                } else if (redirectMode == 'SaveAndNew') {
                    window.open('/setup/ui/recordtypeselect.jsp?ent=' + '{!sobjecttypeForFrontEnd}' + '&retURL=/' + '{!sobjectPrefix}' + '/o&save_new_url=/' + '{!sobjectPrefix}' + '/e?retURL=%2F' + '{!sobjectPrefix}' + '%2Fo', '_self');
                }
            } else {
                // alert(errorMessage);
                alertErrorMessage(errorMessage);
            }
        }
        //Query Required Parameter
        var queryBack = function queryBack(data) {
            console.log('data = ' + data);
            document.querySelector("[data-id='Trial_User__c']").value = data.object.trialUser;
            unblockUI();
        };
        //Check If Insert Or Update
        var insertOrUpdateBack = function insertOrUpdateBack(payloadJson, result, isNewMode) {
            debugger
            console.log(result);
            let r = result;
            console.log('Result from AWS' + JSON.stringify(r));
            console.log('payloadJson=' + JSON.stringify(payloadJson));
            payloadJson.Trial_User__c = r.object[0].trialUser;
            payloadJson.Trail_User_Encrypt__c = r.object[0].trialUserEncrypt;
            payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            if (isNewMode) {
                payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            } else {
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            }
            debugger
            return payloadJson;
        }
        // New Or Edit
        function ProcessPI(consumApplyJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode
            }) {
                NewPIToAWS(consumApplyJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(consumApplyJson, payloadForNewPI)
            }
        }
        //Get Sensitive Information
        function getPIPayload(consumApplyJson) {
            let consumApplyPayloadList = [];
            let trialUser = consumApplyJson.Trial_User__c;
            let consumApplyPIData = new Object();
            consumApplyPIData.trialUser = trialUser;
            consumApplyPIData.sfRecordId = '';
            console.log('consumApply PI Data:' + JSON.stringify(consumApplyPIData));
            consumApplyPayloadList.push(consumApplyPIData);
            console.log(JSON.stringify(consumApplyPayloadList));
            return JSON.stringify(consumApplyPayloadList);
        }
        //Check Validate Field Value
        function validateFieldValueFormate() {
            return true;
        }
        //Get Page Information
        function getConsumApplyInformation() {
            let nodelist = document.querySelectorAll("[data-id]");
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                if (VLookUpFields.has(nodelist[index].getAttribute("data-id"))) {
                    console.log(nodelist[index].id.indexOf('lkwgt'));
                    if (nodelist[index].id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = nodelist[index].id + '_lkid';
                        let vlookUpNodeValue = document.getElementById(vlookUpNodeId).value;
                        result[nodelist[index].getAttribute("data-id")] = vlookUpNodeValue;
                    }
                } else if (nodelist[index].type == 'checkbox') {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].checked;
                } else if (nodelist[index].type == 'select-multiple') {
                    //nodelist[index].getAttribute("data-id")
                    let multiple = nodelist[index].getAttribute("data-id");
                    let targets = document.querySelector("[data-id=" + multiple + "]").parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[nodelist[index].getAttribute("data-id")] = targets;
                } else {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].value;
                }
                let x = index + 1;
                if (x <= nodelist.length - 1 && (nodelist[x].getAttribute("data-id") == nodelist[index].getAttribute("data-id"))) {
                    index++;
                }
            }
            for (let i = 0; i < userVLookUpFields.length; i++) {
                let userVlookUpNodeValue = document.querySelector("[data-id='" + userVLookUpFields[i] + "']").children[1].value;
                console.log('userVlookUpNodeValue:'+userVlookUpNodeValue);
                if(userVlookUpNodeValue!='000000000000000'){
                    result[userVLookUpFields[i]] = userVlookUpNodeValue;
                }
            }
            console.log(JSON.stringify(result));
            return result;
        }
        //Query from AWS
        function QueryConsumApplyFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        //Update Sensitive Information to AWS
        function UpdatePIToAWS(consumApplyJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewConsumApplyEquipSetDetailController.saveConsumApply}';
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, consumApplyJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack, redirectCallBack);
        }
        //Insert Sensitive Information to AWS
        function NewPIToAWS(consumApplyJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewConsumApplyEquipSetDetailController.saveConsumApply}';
            AWSService.insert(staticResources.newUrl, consumApplyJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack, redirectCallBack);
        }
        //Check Required Fields
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for (i = 0; i < requiredFieldAPIList.length; i++) {
                if (formData[requiredFieldAPIList[i]]) {
                    continue;
                } else {
                    if (blankRequiredFields == '') {
                        blankRequiredFields = blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    } else {
                        blankRequiredFields = blankRequiredFields + ',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        //Base Process
        function saveConsumApplyProcess(saveMode) {
            redirectMode = saveMode;
            console.log('redirectMode' + redirectMode);
            hiddenErrorMsgNode();
            //1. Get consumApply Information from Form
            let consumApplyJson = getConsumApplyInformation();
            //2. Validate the consumApply field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (!validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage('邮箱格式输入有误,请重新输入!');
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(consumApplyJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('{!Input_Required_Field_Msg}' + checkRequiredFieldMsgResult);
                return
            }
            //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(consumApplyJson);
            //4. consumApply to AWS
            ProcessPI(consumApplyJson, payloadForNewPI);
        }
        //Alert Error Message
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsg = '错误:无效数据。' + '\n' + errorMsg;
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
            unblockUI();
        }
        //Hide Error Message
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="耗材备品配套一览明细" class="pageTitleIcon" title="耗材备品配套一览明细" />
                <h1 class="pageType">耗材备品配套一览明细编辑
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription">新建耗材备品配套一览明细</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target=consumApplys_edit.htm&amp;section=consumApplys&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <!-- Error Msg-->
        <apex:outputPanel id="errorMsg">
            <apex:pageMessages id="msgContent" escape="false" />
        </apex:outputPanel>
        <apex:pageblock >
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">耗材备品配套一览明细编辑</h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveConsumApplyProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveConsumApplyProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField html-data-id="{!layoutField.fieldAPI}" value="{!Consum_Apply_Equipment_Set_Detail__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                //Append Page
                sfdcPage.appendToOnloadQueue(function () {
                    //2. Query AWS Data by dataId
                    console.log('Mode for consumApply Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QueryConsumApplyFromAWS();
                    };
                    document.querySelector("[data-id='OwnerId']").classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveConsumApplyProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveConsumApplyProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewConsumApplyEquipmentSetDetail.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewConsumApplyEquipmentSetDetail</label>
</ApexPage>
force-app/main/default/pages/NewListOfConsumables.page
New file
@@ -0,0 +1,2 @@
<apex:page >
</apex:page>
force-app/main/default/pages/NewListOfConsumables.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewListOfConsumables</label>
</ApexPage>
force-app/main/default/pages/NewOnCall.page
New file
@@ -0,0 +1,298 @@
<apex:page standardController="On_Call__c" extensions="OnCallController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        //Initial Required Information
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var VLookUpFields = new Set(['segment__c','Hospital__c','Oncall_Equipment__c','OwnerId']);
        var redirectMode = 'Save';
        //Redirect Required Parameter
        var redirectCallBack = function redirectCallBack(sfId, errorMessage) {
            if (sfId) {
                if (redirectMode == 'Save') {
                    window.open('/' + sfId, '_self');
                } else if (redirectMode == 'SaveAndNew') {
                    window.open('/setup/ui/recordtypeselect.jsp?ent=' + '{!sobjecttypeForFrontEnd}' + '&retURL=/' + '{!sobjectPrefix}' + '/o&save_new_url=/' + '{!sobjectPrefix}' + '/e?retURL=%2F' + '{!sobjectPrefix}' + '%2Fo', '_self');
                }
            } else {
                // alert(errorMessage);
                alertErrorMessage(errorMessage);
            }
        }
        //Query Required Parameter
        var queryBack = function queryBack(data) {
            console.log('data = ' + data);
            document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id1:0:j_id2']").value = data.object.callerPhone;
            document.querySelector("[data-id='Responsible_Person_HP__c']").value = data.object.responsiblePersonHP;
            unblockUI();
        };
        //Check If Insert Or Update
        var insertOrUpdateBack = function insertOrUpdateBack(payloadJson, result, isNewMode) {
            debugger
            console.log(result);
            let r = result;
            console.log('Result from AWS' + JSON.stringify(r));
            console.log('payloadJson=' + JSON.stringify(payloadJson));
            payloadJson.Caller_phone__c = r.object[0].callerPhone;
            payloadJson.Responsible_Person_HP__c = r.object[0].responsiblePersonHP;
            payloadJson.Caller_Phone_Encrypt__c = r.object[0].callerPhoneEncrypt;
            payloadJson.Responsible_PersonHP_Encrypt__c = r.object[0].responsiblePersonHPEncrypt;
            payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            if (isNewMode) {
                payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            } else {
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            }
            debugger
            return payloadJson;
        }
        // New Or Edit
        function ProcessPI(onCallJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode
            }) {
                NewPIToAWS(onCallJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(onCallJson, payloadForNewPI)
            }
        }
        //Get Sensitive Information
        function getPIPayload(onCallJson) {
            let onCallPayloadList = [];
            let callerPhone = onCallJson.Caller_phone__c;
            let responsiblePersonHP = onCallJson.Responsible_Person_HP__c;
            let onCallPIData = new Object();
            onCallPIData.callerPhone = callerPhone;
            onCallPIData.responsiblePersonHP = responsiblePersonHP;
            onCallPIData.sfRecordId = '';
            console.log('onCall PI Data:' + JSON.stringify(onCallPIData));
            onCallPayloadList.push(onCallPIData);
            console.log(JSON.stringify(onCallPayloadList));
            return JSON.stringify(onCallPayloadList);
        }
        //Check Validate Field Value
        function validateFieldValueFormate() {
            return true;
        }
        //Get Page Information
        function getOnCallInformation() {
            let nodelist = document.querySelectorAll("[data-id]");
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                if (VLookUpFields.has(nodelist[index].getAttribute("data-id"))) {
                    console.log(nodelist[index].id.indexOf('lkwgt'));
                    if (nodelist[index].id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = nodelist[index].id + '_lkid';
                        let vlookUpNodeValue = document.getElementById(vlookUpNodeId).value;
                        result[nodelist[index].getAttribute("data-id")] = vlookUpNodeValue;
                    }
                } else if (nodelist[index].type == 'checkbox') {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].checked;
                } else if (nodelist[index].type == 'select-multiple') {
                    //nodelist[index].getAttribute("data-id")
                    let multiple = nodelist[index].getAttribute("data-id");
                    let targets = document.querySelector("[data-id=" + multiple + "]").parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[nodelist[index].getAttribute("data-id")] = targets;
                } else {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].value;
                }
                let x = index + 1;
                if (x <= nodelist.length - 1 && (nodelist[x].getAttribute("data-id") == nodelist[index].getAttribute("data-id"))) {
                    index++;
                }
            }
            console.log(JSON.stringify(result));
            return result;
        }
        //Query from AWS
        function QueryOnCallFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        //Update Sensitive Information to AWS
        function UpdatePIToAWS(onCallJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.OnCallController.saveOnCall}';
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, onCallJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack, redirectCallBack);
        }
        //Insert Sensitive Information to AWS
        function NewPIToAWS(onCallJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.OnCallController.saveOnCall}';
            AWSService.insert(staticResources.newUrl, onCallJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack, redirectCallBack);
        }
        //Check Required Fields
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for (i = 0; i < requiredFieldAPIList.length; i++) {
                if (formData[requiredFieldAPIList[i]]) {
                    continue;
                } else {
                    if (blankRequiredFields == '') {
                        blankRequiredFields = blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    } else {
                        blankRequiredFields = blankRequiredFields + ',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        //Base Process
        function saveOnCallProcess(saveMode) {
            redirectMode = saveMode;
            console.log('redirectMode' + redirectMode);
            hiddenErrorMsgNode();
            //1. Get onCall Information from Form
            let onCallJson = getOnCallInformation();
            //2. Validate the onCall field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (!validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage('邮箱格式输入有误,请重新输入!');
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(onCallJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('{!Input_Required_Field_Msg}' + checkRequiredFieldMsgResult);
                return
            }
            //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(onCallJson);
            //4. onCall to AWS
            ProcessPI(onCallJson, payloadForNewPI);
        }
        //Alert Error Message
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsg = '错误:无效数据。' + '\n' + errorMsg;
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
            unblockUI();
        }
        //Hide Error Message
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="OnCall" class="pageTitleIcon" title="OnCall" />
                <h1 class="pageType">OnCall编辑
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription">新建OnCall</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target=onCalls_edit.htm&amp;section=onCalls&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <!-- Error Msg-->
        <apex:outputPanel id="errorMsg">
            <apex:pageMessages id="msgContent" escape="false" />
        </apex:outputPanel>
        <apex:pageblock >
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">OnCall编辑</h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveOnCallProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveOnCallProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField html-data-id="{!layoutField.fieldAPI}" value="{!On_Call__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                //Append Page
                sfdcPage.appendToOnloadQueue(function () {
                    //2. Query AWS Data by dataId
                    console.log('Mode for onCall Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QueryOnCallFromAWS();
                    };
                    document.querySelector("[data-id='OwnerId']").classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveOnCallProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveOnCallProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewOnCall.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewOnCall</label>
</ApexPage>
force-app/main/default/pages/NewRentalApply.page
New file
@@ -0,0 +1,387 @@
<apex:page standardController="Rental_Apply__c" extensions="RentalApplyController" id="page">
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        //Initial Required Information
        var staticResources = JSON.parse('{!staticResource}');
        var staticResourcesContact = JSON.parse('{!staticResourceContact}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var VLookUpFields = new Set(['OwnerId','OPDPlan__c','Zsq_Rental_Apply__c','Loaner_medical_Staff__c','Hospital__c','Strategic_dept__c','Account__c','Repair__c','Campaign__c','QIS_number__c','QISRepair__c','NewRepair__c','Follow_UP_Opp__c','Statu_Achievements__c','Shipment_address__c','Dealer__c','Old_Rental_Apply__c','OPD__c']);
        var userVLookUpFields = ['Person_In_Charge__c','applyUser__c','Rental_Assistant__c','Assign_Person__c','ZongjianApprovalManager__c','BuchangApprovalManager__c','JingliApprovalManager__c','BuchangApprovalManagerSales__c','SalesManager__c'];
        var redirectMode = 'Save';
        //Redirect Required Parameter
        var redirectCallBack = function redirectCallBack(sfId,errorMessage) {
            if(sfId){
                if (redirectMode == 'Save') {
                window.open('/' + sfId, '_self');
            } else if (redirectMode == 'SaveAndNew') {
                window.open('/a3i/e', '_self');
            }
            }else{
                // alert(errorMessage);
                alertErrorMessage(errorMessage);
            }
        }
        //Query Required Parameter
        var queryBack = function queryBack(data) {
            console.log('data = ' + data);
            document.querySelector("[data-id='Phone_number__c']").value = data.object.phoneNumber;
            document.querySelector("[data-id='direct_shippment_address__c']").value = data.object.directShippmentAddress;
            unblockUI();
        };
        //Check If Insert Or Update
        var insertOrUpdateBack = function insertOrUpdateBack(payloadJson, result, isNewMode) {
            debugger
            console.log(result);
            let r = result;
            console.log('Result from AWS' + JSON.stringify(r));
            console.log('payloadJson=' + JSON.stringify(payloadJson));
            payloadJson.Phone_number__c = r.object[0].phoneNumber;
            payloadJson.direct_shippment_address__c = r.object[0].directShippmentAddress;
            payloadJson.Phone_Number_Encrypt__c = r.object[0].phoneNumberEncrypt;
            payloadJson.Direct_Shippment_Address_Encrypt__c = r.object[0].directShippmentAddressEncrypt;
            payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            if (isNewMode) {
                payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            } else {
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            }
            debugger
            return payloadJson;
        }
        // New Or Edit
        function ProcessPI(rentalApplyJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode
            }) {
                NewPIToAWS(rentalApplyJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(rentalApplyJson, payloadForNewPI)
            }
        }
        //Get Sensitive Information
        function getPIPayload(rentalApplyJson) {
            let rentalApplyPayloadList = [];
            let phoneNumber = rentalApplyJson.Phone_number__c;
            let directShippmentAddress = rentalApplyJson.direct_shippment_address__c;
            let rentalApplyPIData = new Object();
            rentalApplyPIData.phoneNumber = phoneNumber;
            rentalApplyPIData.directShippmentAddress = directShippmentAddress;
            rentalApplyPIData.sfRecordId = '';
            console.log('rentalApply PI Data:' + JSON.stringify(rentalApplyPIData));
            rentalApplyPayloadList.push(rentalApplyPIData);
            console.log(JSON.stringify(rentalApplyPayloadList));
            return JSON.stringify(rentalApplyPayloadList);
        }
        //Check Validate Field Value
        function validateFieldValueFormate() {
            return true;
        }
        //Get Page Information
        function getRentalApplyInformation() {
            let nodelist = document.querySelectorAll("[data-id]");
            let result = {}
            //富文本
            if(document.querySelector("[aria-describedby = 'cke_34']")){
                result.HP_received_sign_rich__c = document.querySelector("[aria-describedby = 'cke_34']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            }
            for (let index = 0; index < nodelist.length; index++) {
                if (VLookUpFields.has(nodelist[index].getAttribute("data-id"))) {
                    console.log(nodelist[index].id.indexOf('lkwgt'));
                    if (nodelist[index].id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = nodelist[index].id + '_lkid';
                        let vlookUpNodeValue = document.getElementById(vlookUpNodeId).value;
                        result[nodelist[index].getAttribute("data-id")] = vlookUpNodeValue;
                    }
                } else if (nodelist[index].type == 'checkbox') {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].checked;
                } else if (nodelist[index].type == 'select-multiple') {
                    //nodelist[index].getAttribute("data-id")
                    let multiple = nodelist[index].getAttribute("data-id");
                    let targets = document.querySelector("[data-id=" + multiple + "]").parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[nodelist[index].getAttribute("data-id")] = targets;
                } else {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].value;
                }
                let x = index + 1;
                if (x <= nodelist.length - 1 && (nodelist[x].getAttribute("data-id") == nodelist[index].getAttribute("data-id"))) {
                    index++;
                }
            }
            for (let i = 0; i < userVLookUpFields.length; i++) {
                let userVlookUpNodeValue = document.querySelector("[data-id='" + userVLookUpFields[i] + "']").children[1].value;
                console.log('userVlookUpNodeValue:'+userVlookUpNodeValue);
                if(userVlookUpNodeValue!='000000000000000'){
                    result[userVLookUpFields[i]] = userVlookUpNodeValue;
                }
            }
            //page:form:j_id30:j_id34:2:j_id35:j_id36:2:j_id37
            //page:form:j_id27:j_id31:2:j_id32:j_id33:2:j_id34
            result.demo_purpose2__c = document.querySelector("[id='page:form:j_id30:j_id34:2:j_id35:j_id36:2:j_id37']").value;
            result.ToAgency__c = document.querySelector("[id='page:form:j_id30:j_id34:0:j_id35:j_id36:14:j_id37']").value;
            result.Loaner_cancel_reason__c = document.querySelector("[id='page:form:j_id30:j_id34:0:j_id35:j_id36:14:j_id37']").value;
            console.log(JSON.stringify(result));
            return result;
        }
        //Query from AWS
        function QueryRentalApplyFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        //Update Sensitive Information to AWS
        function UpdatePIToAWS(rentalApplyJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.RentalApplyController.saveRentalApply}';
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, rentalApplyJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack, redirectCallBack);
        }
        //Insert Sensitive Information to AWS
        function NewPIToAWS(rentalApplyJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.RentalApplyController.saveRentalApply}';
            AWSService.insert(staticResources.newUrl, rentalApplyJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack, redirectCallBack);
        }
        //Check Required Fields
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for (i = 0; i < requiredFieldAPIList.length; i++) {
                if (formData[requiredFieldAPIList[i]]) {
                    continue;
                } else {
                    if (blankRequiredFields == '') {
                        blankRequiredFields = blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    } else {
                        blankRequiredFields = blankRequiredFields + ',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        //Base Process
        function saveRentalApplyProcess(saveMode) {
            redirectMode = saveMode;
            console.log('redirectMode' + redirectMode);
            hiddenErrorMsgNode();
            //1. Get rentalApply Information from Form
            let rentalApplyJson = getRentalApplyInformation();
            //2. Validate the rentalApply field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (!validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage('邮箱格式输入有误,请重新输入!');
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(rentalApplyJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('{!Input_Required_Field_Msg}' + checkRequiredFieldMsgResult);
                return
            }
            //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(rentalApplyJson);
            //4. rentalApply to AWS
            ProcessPI(rentalApplyJson, payloadForNewPI);
        }
        //Alert Error Message
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsg = '错误:无效数据。' + '\n' + errorMsg;
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
            unblockUI();
        }
        //Hide Error Message
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        //替换vlookup
        function replaceSearchContactLookup() {
            let lookUpNode = htmlToElement(contactHtmlString);
            console.log(lookUpNode);
            if (!{!isNewMode}) {
                queryContactName();
            }
            let parentNode = document.querySelector("[data-id='Loaner_medical_Staff__c']").parentNode;
            document.querySelector("[data-id='Loaner_medical_Staff__c']").removeAttribute("onchange");
            parentNode.replaceChild(lookUpNode, document.querySelector("[data-id='Loaner_medical_Staff__c']").parentNode.children[2]);
        }
        var newSearchContactWindow = null;
        var contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'page:form:contactId\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
        function htmlToElement(html) {
            var template = document.createElement('template');
            html = html.trim(); // Never return a text node of whitespace as the result
            template.innerHTML = html;
            return template.content.firstChild;
        }
        function queryContactName() {
            let sfId = document.getElementById(document.querySelector("[data-id='Loaner_medical_Staff__c']").id + '_lkid').value;
            let contactsInfo = JSON.parse('{!contactsInfo}');
            let dataId = contactsInfo[sfId];
            let url = staticResourcesContact.queryUrl + '?dataId=' + dataId;
            fetch(url, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then((result) => {
                document.querySelector("[data-id='Loaner_medical_Staff__c']").value = result.object.lastName;
            })
        }
        //自定义lookup查询
        function searchContact(contactNodeId){
            let accountValue = "";
            if (document.querySelector("[data-id='Account__c']")) {
                let accountNodeId = document.querySelector("[data-id='Account__c']").id + '_lkid';
                accountValue = document.getElementById(accountNodeId).value;
            }
            console.log(accountValue);
            if(accountValue !='000000000000000'){
                let baseUrl = "/apex/SearchContactPage";
                let suffixUrl = "?contactId="+contactNodeId+"&accountId="+accountValue;
                let newSearchContactParam = 'height=600,width=800,left=100,top=100,dialogHide=true,resizable=no,scrollbars=yes,toolbar=no,status=no';
                newSearchContactWindow = window.open(baseUrl+suffixUrl, 'Popup', newSearchContactParam);
                if (window.focus) {
                    newSearchContactWindow.focus();
                }
                return false;
            }else{
                alertErrorMessage('{!PIPL_Input_Account_Error_Msg}');
            }
        }
        //窗口关闭时发生
        function closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            let contactInfoStr = document.getElementById('page:form:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = document.querySelector("[data-id='Loaner_medical_Staff__c']").id + '_lkid';
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.querySelector("[data-id='Loaner_medical_Staff__c']").value = contactInfo.Name;
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="备品借出申请" class="pageTitleIcon" title="备品借出申请" />
                <h1 class="pageType">备品借出申请编辑
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription"> 新建备品借出申请</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target=rentalApplys_edit.htm&amp;section=rentalApplys&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <apex:inputHidden value="{!contactId}" id="contactId"/>
        <!-- Error Msg-->
        <apex:outputPanel id="errorMsg">
            <apex:pageMessages id="msgContent" escape="false" />
        </apex:outputPanel>
        <apex:pageblock >
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">备品借出申请编辑</h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveRentalApplyProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveRentalApplyProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField html-data-id="{!layoutField.fieldAPI}" value="{!Rental_Apply__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                //Append Page
                sfdcPage.appendToOnloadQueue(function () {
                    //2. Query AWS Data by dataId
                    console.log('Mode for rentalApply Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QueryRentalApplyFromAWS();
                    };
                    //Replace Vlookup Field
                    replaceSearchContactLookup();
                    document.querySelector("[data-id='OwnerId']").classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveRentalApplyProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveRentalApplyProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewRentalApply.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewRentalApply</label>
</ApexPage>
force-app/main/default/pages/NewRepair.page
New file
@@ -0,0 +1,327 @@
<apex:page standardController="Repair__c" extensions="NewRepairController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <style>
        .disabledbutton {
            pointer-events: none;
            opacity: 0.4;
        }
    </style>
    <script>
        //Initial Required Information
        var staticResources = JSON.parse('{!staticResource}');
        var requiredFieldAPIList = JSON.parse('{!requiredFieldAPIListStr}');
        var fieldAPIToLabelMap = JSON.parse('{!fieldAPIToLabelMapStr}');
        var VLookUpFields = new Set(['Delivered_Product__c','Hospital__c','Department_Class__c','Account__c','Dealer__c','Incharge_Staff_Contact__c','Maintenance_Contract__c','VM_Maintenance_Contract__c','Repair_Quotation_Id__c','RepairSubOrder__c','On_Call_ID__c','QIS_ID__c','InsReport__c','NFM108_Receipt__c','Rental_Apply_Equipment_Set_Detail__c']);
        var userVLookUpFields = ['Incharge_Staff__c','Repair_Authenticator__c','OCSM_RC_CordingUser__c','OSH_Affirmant__c','OSHRAConfirmUser__c'];
        var redirectMode = 'Save';
        //Redirect Required Parameter
        var redirectCallBack = function redirectCallBack(sfId, errorMessage) {
            if (sfId) {
                if (redirectMode == 'Save') {
                    window.open('/' + sfId, '_self');
                } else if (redirectMode == 'SaveAndNew') {
                    window.open('/setup/ui/recordtypeselect.jsp?ent=' + '{!sobjectId}' + '&retURL=/' + '{!sobjectPrefix}' + '/o&save_new_url=/' + '{!sobjectPrefix}' + '/e?retURL=%2F' + '{!sobjectPrefix}' + '%2Fo', '_self');
                }
            } else {
                // alert(errorMessage);
                alertErrorMessage(errorMessage);
            }
        }
        //Query Required Parameter
        var queryBack = function queryBack(data) {
            console.log('data = ' + data);
            document.querySelector("[data-id='address_Contacts__c']").value = data.object.addressContacts;
            document.querySelector("[data-id='address_Contacts_Name__c']").value = data.object.addressContactsName;
            document.querySelector("[data-id='address_Telephone__c']").value = data.object.addressTelephone;
            document.querySelector("[data-id='address_ZipCode__c']").value = data.object.addressZipCode;
            document.querySelector("[data-id='Detailed_Address__c']").value = data.object.detailedAddress;
            document.querySelector("[data-id='RepairApplicant__c']").value = data.object.repairApplicant;
            unblockUI();
        };
        //Check If Insert Or Update
        var insertOrUpdateBack = function insertOrUpdateBack(payloadJson, result, isNewMode) {
            debugger
            console.log(result);
            let r = result;
            console.log('Result from AWS' + JSON.stringify(r));
            console.log('payloadJson=' + JSON.stringify(payloadJson));
            payloadJson.address_Contacts__c = r.object[0].addressContacts;
            payloadJson.address_Contacts_Name__c = r.object[0].addressContactsName;
            payloadJson.address_Telephone__c = r.object[0].addressTelephone;
            payloadJson.address_ZipCode__c = r.object[0].addressZipCode;
            payloadJson.Detailed_Address__c = r.object[0].detailedAddress;
            payloadJson.RepairApplicant__c = r.object[0].repairApplicant;
            payloadJson.Address_Contacts_Encrypt__c = r.object[0].addressContactsEncrypt;
            payloadJson.Address_Contacts_Name_Encrypt__c = r.object[0].addressContactsNameEncrypt;
            payloadJson.Address_Telephone_Encrypt__c = r.object[0].addressTelephoneEncrypt;
            payloadJson.Address_ZipCode_Encrypt__c = r.object[0].addressZipCodeEncrypt;
            payloadJson.Detailed_Address_Encrypt__c = r.object[0].detailedAddressEncrypt;
            payloadJson.Repair_Applicant_Encrypt__c = r.object[0].repairApplicantEncrypt;
            payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            if (isNewMode) {
                payloadJson.AWS_Data_Id__c = r.object[0].dataId;
            } else {
                payloadJson.AWS_Data_Id__c = '{!AWSDataId}';
            }
            debugger
            return payloadJson;
        }
        // New Or Edit
        function ProcessPI(repairJson, payloadForNewPI) {
            blockme();
            if ({!isNewMode
            }) {
                NewPIToAWS(repairJson, payloadForNewPI)
            }else {
                UpdatePIToAWS(repairJson, payloadForNewPI)
            }
        }
        //Get Sensitive Information
        function getPIPayload(repairJson) {
            let repairPayloadList = [];
            let addressContacts = repairJson.address_Contacts__c;
            let addressContactsName = repairJson.address_Contacts_Name__c;
            let addressTelephone = repairJson.address_Telephone__c;
            let addressZipCode = repairJson.address_ZipCode__c;
            let detailedAddress = repairJson.Detailed_Address__c;
            let repairApplicant = repairJson.RepairApplicant__c;
            let repairPIData = new Object();
            repairPIData.addressContacts = addressContacts;
            repairPIData.addressContactsName = addressContactsName;
            repairPIData.addressTelephone = addressTelephone;
            repairPIData.addressZipCode = addressZipCode;
            repairPIData.detailedAddress = detailedAddress;
            repairPIData.repairApplicant = repairApplicant;
            repairPIData.sfRecordId = '';
            console.log('repair PI Data:' + JSON.stringify(repairPIData));
            repairPayloadList.push(repairPIData);
            console.log(JSON.stringify(repairPayloadList));
            return JSON.stringify(repairPayloadList);
        }
        //Check Validate Field Value
        function validateFieldValueFormate() {
            return true;
        }
        //Get Page Information
        function getRepairInformation() {
            let nodelist = document.querySelectorAll("[data-id]");
            let result = {}
            for (let index = 0; index < nodelist.length; index++) {
                if (VLookUpFields.has(nodelist[index].getAttribute("data-id"))) {
                    console.log(nodelist[index].id.indexOf('lkwgt'));
                    if (nodelist[index].id.indexOf('lkwgt') == -1) {
                        let vlookUpNodeId = nodelist[index].id + '_lkid';
                        let vlookUpNodeValue = document.getElementById(vlookUpNodeId).value;
                        result[nodelist[index].getAttribute("data-id")] = vlookUpNodeValue;
                    }
                } else if (nodelist[index].type == 'checkbox') {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].checked;
                } else if (nodelist[index].type == 'select-multiple') {
                    //nodelist[index].getAttribute("data-id")
                    let multiple = nodelist[index].getAttribute("data-id");
                    let targets = document.querySelector("[data-id=" + multiple + "]").parentNode.children[1].children[0].children[1].children[2].children[0].innerText;
                    targets = targets.replace(/\n/g, ";");
                    console.log('targets = ' + targets);
                    result[nodelist[index].getAttribute("data-id")] = targets;
                } else {
                    result[nodelist[index].getAttribute("data-id")] = nodelist[index].value;
                }
                let x = index + 1;
                if (x <= nodelist.length - 1 && (nodelist[x].getAttribute("data-id") == nodelist[index].getAttribute("data-id"))) {
                    index++;
                }
            }
            for (let i = 0; i < userVLookUpFields.length; i++) {
                let userVlookUpNodeValue = document.querySelector("[data-id='" + userVLookUpFields[i] + "']").children[1].value;
                console.log('userVlookUpNodeValue:'+userVlookUpNodeValue);
                if(userVlookUpNodeValue!='000000000000000'){
                    result[userVLookUpFields[i]] = userVlookUpNodeValue;
                }
            }
            result.work_location_select__c = document.querySelector("[id='page:form:j_id30:j_id34:0:j_id35:j_id36:18:j_id37']").value;
            // result.ProblemDescription__c = document.querySelector("[aria-describedby = 'cke_34']").contentWindow.document.getElementsByTagName('body')[0].innerHTML
            console.log(JSON.stringify(result));
            return result;
        }
        //Query from AWS
        function QueryRepairFromAWS() {
            AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
        }
        //Update Sensitive Information to AWS
        function UpdatePIToAWS(repairJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewRepairController.saveRepair}';
            let obj = JSON.parse(payloadForNewPI);
            obj[0].dataId = '{!AWSDataId}';
            let payloadForNewPIJson = JSON.stringify(obj);
            AWSService.update(staticResources.updateUrl, repairJson, payloadForNewPIJson, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, false, insertOrUpdateBack, redirectCallBack);
        }
        //Insert Sensitive Information to AWS
        function NewPIToAWS(repairJson, payloadForNewPI) {
            let controllerSaveMethod = '{!$RemoteAction.NewRepairController.saveRepair}';
            AWSService.insert(staticResources.newUrl, repairJson, payloadForNewPI, controllerSaveMethod, staticResources.token, staticResources.transactionUrl, true, insertOrUpdateBack, redirectCallBack);
        }
        //Check Required Fields
        function checkRequiredFieldMsg(formData) {
            let blankRequiredFields = '';
            for (i = 0; i < requiredFieldAPIList.length; i++) {
                if (formData[requiredFieldAPIList[i]]) {
                    continue;
                } else {
                    if (blankRequiredFields == '') {
                        blankRequiredFields = blankRequiredFields + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    } else {
                        blankRequiredFields = blankRequiredFields + ',' + fieldAPIToLabelMap[requiredFieldAPIList[i]];
                    }
                }
            }
            return blankRequiredFields;
        }
        //Base Process
        function saveRepairProcess(saveMode) {
            redirectMode = saveMode;
            console.log('redirectMode' + redirectMode);
            hiddenErrorMsgNode();
            //1. Get repair Information from Form
            let repairJson = getRepairInformation();
            //2. Validate the repair field value formate, for example the email formate or phone formate
            let validationResultMessage = validateFieldValueFormate();
            console.log(validationResultMessage);
            if (!validationResultMessage) {
                //Popup error message.  - To Do After POC
                alertErrorMessage('邮箱格式输入有误,请重新输入!');
                return
            }
            // Check Required Field
            let checkRequiredFieldMsgResult = checkRequiredFieldMsg(repairJson);
            if (checkRequiredFieldMsgResult) {
                alertErrorMessage('{!Input_Required_Field_Msg}' + checkRequiredFieldMsgResult);
                return
            }
            //3. Prepare the payload for New PI API To AWS - To Do
            let payloadForNewPI = getPIPayload(repairJson);
            //4. repair to AWS
            ProcessPI(repairJson, payloadForNewPI);
        }
        //Alert Error Message
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsg = '错误:无效数据。' + '\n' + errorMsg;
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'pbError';
            unblockUI();
        }
        //Hide Error Message
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:form:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
    </script>
    <div class="bPageTitle">
        <div class="ptBody">
            <div class="content">
                <img src="/img/s.gif" alt="修理" class="pageTitleIcon" title="修理" />
                <h1 class="pageType">修理编辑
                    <span class="titleSeparatingColon">:</span>
                </h1>
                <h2 class="pageDescription">新建修理</h2>
                <div class="blank">&nbsp;</div>
            </div>
            <div class="links">
                <a href="javascript:openPopupFocusEscapePounds(%27https://help.salesforce.com/apex/htdoor?loc=help&amp;target=repairs_edit.htm&amp;section=repairs&amp;language=zh_CN&amp;release=234.18.8&amp;instance=CS117&amp;showSplash=true%27, %27Help%27, 700, 600, %27width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no%27, false, false);"
                    title="此页面的帮助 (新窗口)">
                    <span class="helpLink">此页面的帮助</span>
                    <img src="/img/s.gif" alt="" class="helpIcon" />
                </a>
            </div>
        </div>
        <div class="ptBreadcrumb"></div>
    </div>
    <apex:form id="form">
        <!-- Error Msg-->
        <apex:outputPanel id="errorMsg">
            <apex:pageMessages id="msgContent" escape="false" />
        </apex:outputPanel>
        <apex:pageblock >
            <div class="pbHeader">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />
                                <h2 class="mainTitle">修理编辑</h2>
                            </td>
                            <td class="pbButton" id="topButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveRepairProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveRepairProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <!-- Iterate the layoutSections, which is a list of sections -->
            <apex:repeat value="{!layoutSections}" var="layoutSection">
                <apex:pageBlockSection title="{!layoutSection.name}" collapsible="{!layoutSection.allowCollapse}" columns="{!layoutSection.columns}">
                    <!--Each section has layoutFields, let's iterate them as well-->
                    <apex:repeat value="{!layoutSection.layoutFields}" var="layoutField">
                        <apex:inputField html-data-id="{!layoutField.fieldAPI}" value="{!Repair__c[layoutField.fieldAPI]}" rendered="{!not(layoutField.isPlaceHOlder)}"
                            required="{!layoutField.isRequired}" />
                        <apex:pageblocksectionitem rendered="{!layoutField.isPlaceHolder}">
                        </apex:pageblocksectionitem>
                    </apex:repeat>
                </apex:pageBlockSection>
            </apex:repeat>
            <script>
                //Append Page
                sfdcPage.appendToOnloadQueue(function () {
                    //2. Query AWS Data by dataId
                    console.log('Mode for repair Page:' + {!isNewMode});
                    if (!{!isNewMode}) {
                        blockme();
                        QueryRepairFromAWS();
                    };
                    document.querySelector("[data-id='OwnerId']").classList.add("disabledbutton");
                });
            </script>
            <div class="pbBottomButtons">
                <table cellspacing="0" cellpadding="0" border="0">
                    <tbody>
                        <tr>
                            <td class="pbTitle">
                                <img src="/img/s.gif" alt="" class="minWidth" title="" width="1" height="1" />&nbsp;</td>
                            <td class="pbButtonb" id="bottomButtonRow">
                                <input class="btn" type="Button" value="保存" onclick="saveRepairProcess('Save')" />
                                <input class="btn" type="Button" value="保存并新建" onclick="saveRepairProcess('SaveAndNew')" />
                                <apex:commandButton action="{!cancel}" value="取消" />
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/NewRepair.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewRepair</label>
</ApexPage>
force-app/main/default/pages/NewRepairPage.page
New file
@@ -0,0 +1,2 @@
<apex:page >
</apex:page>
force-app/main/default/pages/NewRepairPage.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>NewRepairPage</label>
</ApexPage>
force-app/main/default/pages/RentalApplyUploadPdf.page
New file
@@ -0,0 +1,190 @@
<!-- 该页面用于Lead对象上传PDF,未来如果要添加其他对象的上传PDF功能,复制该页面,将**standardController**修改为其他对象API名称即可 -->
<apex:page standardController="Rental_Apply__c" extensions="FileUploadController" id="page" lightningStyleSheets="true">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script>
        var staticResources = JSON.parse('{!staticResource}');
        var parentId = '{!parentId}';
        var uploadUrl = staticResources.newUrl;
        var key;
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:theForm:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'message errorM3';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:theForm:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        function getFileContent(event) {
            var fileObject = document.getElementById("page:theForm:block:uploadSection:file");
            var reader = new FileReader();
            var data = reader.readAsDataURL(fileObject.files[0]);
            debugger
            console.log(event);
        }
        function getBase64(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = () => resolve(reader.result);
                reader.onerror = error => reject(error);
            });
        }
        function disableButtonStatus() {
            let btnNode = document.getElementById('uploadFileId');
            btnNode.classList.add("btnDisabled");
        }
        function enableButtonStatus() {
            let btnNode = document.getElementById('uploadFileId');
            btnNode.classList.remove("btnDisabled");
        }
        function uploadFile() {
            disableButtonStatus();
            var fileObject = document.getElementById("file").files[0];
            getBase64(fileObject).then(
                data => {
                    console.log(data);
                    uploadFileToAWS(data, (fileObject.size).toString(), fileObject.name);
                }
            );
        }
        function confirmTrans(transId, isSuccess) {
            fetch(staticResources.updateUrl, {
                method: 'POST',
                body: JSON.stringify({ 'txId': transId, "isSuccess": isSuccess }),
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then(data => {
                console.log("confirmTrans-" + JSON.stringify(data));
                document.getElementById("file").files[0].name = '';
                enableButtonStatus();
                refreshFiles();
                return data.status;
            })
        }
        function calculateFileSize(fileObject) {
            if (fileObject.size > 20971520) {
                alertErrorMessage('文件过大,请选择小于20mb的文件');
            }
        }
        function uploadFileToAWS(data, size, fileName) {
            console.log("body=" + JSON.stringify({ 'file': data, "size": size, 'fileName': fileName }));
            fetch(uploadUrl, {
                method: 'POST',
                body: JSON.stringify({ 'file': data, "size": size, 'fileName': fileName }),
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then(result => {
                console.log("result" + JSON.stringify(result));
                if (result.success == true) {
                    key = result.object;
                    Visualforce.remoting.Manager.invokeAction(
                        '{!$RemoteAction.FileUploadController.saveFile}',
                        fileName, key, result.txId, parentId,
                        function (resultvalue, event) {
                            //2. show file list
                            if (resultvalue.status == 'fail') {
                                alertErrorMessage(resultvalue.message);
                                //1. Confirm trans
                                confirmTrans(result.txId, 0);
                            } else {
                                alertErrorMessage('上传成功');
                                confirmTrans(result.txId, 1);
                            }
                            // window.location.reload();
                        },
                        { escape: true }
                    );
                    console.log('key' + key);
                } else {
                    alertErrorMessage('上传失败请稍后再试!');
                }
            }).catch((error) => {
                console.error('Error:', error);
            })
            debugger
        }
        function downPdf(fileUrl) {
            window.open(fileUrl,'_blank');
        }
    </script>
    <style>
        .pdf .num {
            width: 30%;
        }
        .pdf.name {
            width: 30%
        }
        .pdf.downLink {
            width: 40%
        }
    </style>
    <apex:form id="theForm">
        <apex:actionFunction name="refreshFiles" action="{!refreshFiles}" reRender="pdf,uploadSection"/>
        <br/>
        <br/>
        <apex:pageBlock id="block">
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <apex:pageBlockSection id="uploadSection">
                <!-- <apex:inputFile id="file" value="{!documentData.body}" filename="{!documentData.name}" /> -->
                <input type="file" id="file" name="filename"/>
                <input class="btn" id='uploadFileId' type="Button" value="确认上传" onclick="uploadFile()" />
            </apex:pageBlockSection>
        </apex:pageBlock>
        <apex:pageBlock title="PDF列表" id="pdf">
            <!-- <apex:pageBlockSection > -->
            <!-- show uploated file list -->
            <apex:pageBlockTable value="{!fileList}" var="file" align="center" columns="3" columnsWidth="30%,30%,40%">
                <apex:column id="name" headerValue="文件名称">
                    <apex:outputLink value="/{!file.Id}" target="_blank">{!file.FileName__c}</apex:outputLink>
                </apex:column>
                <!-- <apex:column id="num" headerValue="父记录链接">
                    <apex:outputLink value="/{!file.ParentRecordId__c}" target="_blank">{!file.ParentRecordId__c}</apex:outputLink>
                </apex:column> -->
                <apex:column id="previewLink" headerValue="预览链接">
                    <apex:outputLink value="{!file.ViewLink__c}" target="{!file.ViewLink__c}">预览链接
                    </apex:outputLink>
                </apex:column>
                <apex:column id="downLink" headerValue="下载链接">
                    <!-- <apex:outputLink value= "{!file.DownloadLink__c}" target="{!file.DownloadLink__c}">下载链接
                    </apex:outputLink> -->
                    <input class="btn" id='downloadFileButton' type="Button" value="下载" onclick="downPdf('{!file.DownloadLink__c}')" />
                </apex:column>
            </apex:pageBlockTable>
            <!-- </apex:pageBlockSection> -->
        </apex:pageBlock>
    </apex:form>
</apex:page>
force-app/main/default/pages/RentalApplyUploadPdf.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>RentalApplyUploadPdf</label>
</ApexPage>
force-app/main/default/pages/SearchContactPage.page
New file
@@ -0,0 +1,185 @@
<apex:page controller="SearchContactController" showHeader="false" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <head>
    </head>
    <style>
        /* 1. 定义表单样式 To Do Later*/
        table {
            border-collapse: collapse;
            border-spacing: 0;
            width: 98%;
            margin-left: 5px;
        }
    </style>
    <body id="body" class="lookupTab">
        <script type="text/javascript">
            var staticResources = JSON.parse('{!staticResource}');
            var contactAWSIds = JSON.parse('{!contactAWSIds}');
            var contactsInfo = JSON.parse('{!contactsInfo}');
            var searchContactName = '';
            queryLeadFromAWS();
            function searchAWSContact(){
                console.log('Search process!');
                //1. reset table;
                resetTable();
                //2. get contact name value
                searchContactName = document.getElementById('page:form:lksrch').value;
                queryLeadFromAWS();
            }
            function resetTable(){
                let queryResult = document.getElementById('QueryResult');
                let table = document.getElementById('table');
                if(table){
                    queryResult.removeChild(table);
                }
            }
            function preparePayloadForSearchContact(){
                let searchPayload = new Object();
                searchPayload.dataIds = contactAWSIds;
                searchPayload.contactName = searchContactName;
                return JSON.stringify(searchPayload);
            }
            function queryLeadFromAWS() {
                //1. Prepare the payload for contact search
                let requestSearchPayload = preparePayloadForSearchContact();
                console.log('request payload body:'+requestSearchPayload);
                //2. Invoke AWS Service
                fetch(staticResources.searchUrl, {
                    method: 'POST',
                    body: requestSearchPayload,
                    headers: {
                        'Content-Type': 'application/json',
                        'pi-token': staticResources.token
                    }
                }).then((data) => {
                    return data.json();
                }).then((result) => {
                    if(result.object&&result.object.length>0){
                        initContactTable(result);
                    }
                })
            }
            function redirectToParentPage(obj) {
                var winMain = window.opener;
                if (null == winMain) {
                    winMain = window.parent.opener;
                }
                let value = obj.currentTarget.innerText;
                let contactInfo = new Object();
                contactInfo.Name = obj.currentTarget.innerText;
                contactInfo.ContactId = obj.currentTarget.id;
                var selectedContactNode = winMain.document.getElementById('{!JSENCODE($CurrentPage.parameters.contactId)}');
                selectedContactNode.value = JSON.stringify(contactInfo);
                closeWindow();
            }
            function closeWindow() {
                var winMain = window.opener;
                if (null == winMain) {
                    winMain = window.parent.opener;
                }
                winMain.closePopupWindow();
                window.close();
            }
            function refreshTable(cols,contactInfoList){
                let myTableDiv = document.getElementById("QueryResult");
                let table = document.createElement('TABLE');
                table.border = '1';
                table.id = 'table'
                let tableBody = document.createElement('TBODY');
                table.appendChild(tableBody);
                let headerTR = document.createElement('TR');
                tableBody.appendChild(headerTR);
                for (let i = 0; i < cols.length; i++) {
                    let td = document.createElement('TH');
                    td.width = '75';
                    td.appendChild(document.createTextNode(cols[i]));
                    headerTR.appendChild(td);
                }
                //3. Init the AWS data
                for (let i = 0; i < contactInfoList.length; i++) {
                    let tr = document.createElement('TR');
                    tableBody.appendChild(tr);
                    let contactInfoTemp = contactInfoList[i]
                    for (let j = 0; j < cols.length; j++) {
                        let td = document.createElement('TD');
                        td.width = '75';
                        if(j == 0){
                            td.id = contactsInfo[contactInfoTemp.AWSDataId].Id;
                        }
                        td.appendChild(document.createTextNode(contactInfoTemp[cols[j]]));
                        if (cols[j] == 'Name') {
                            td.addEventListener("click", function (obj) {
                                redirectToParentPage(obj);
                            });
                        }
                        tr.appendChild(td);
                    }
                }
                myTableDiv.appendChild(table);
            }
            function initContactTable(data) {
                let cols = ['Name', 'Email', 'Phone'];
                let contactInfoList = [];
                let awsDataIds = [];
                for(var i=0;i<data.object.length;i++){
                    if(data.object[i].dataId){
                        let contactInfo = new Object();
                        contactInfo.Name = data.object[i].lastName;
                        contactInfo.Email = data.object[i].email;
                        contactInfo.Phone = data.object[i].phone;
                        contactInfo.AWSDataId = data.object[i].dataId;
                        awsDataIds.push(contactInfo.AWSDataId);
                        contactInfo.sfRecordId = '';
                        contactInfoList.push(contactInfo);
                    }
                }
                let AWSIdToSFIdMapValue = {};
                console.log(awsDataIds);
                //Invoke SF BackEnd
                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.SearchContactController.searchContacts}',
                    JSON.stringify(awsDataIds),
                    function (result, event) {
                        if(event.status){
                            if(result.status = 'success'){
                                contactsInfo = JSON.parse(result.message.replace(/(&quot\;)/g,"\""));
                                refreshTable(cols,contactInfoList);
                            }else{
                                console.log('No result');
                            }
                        }
                    },
                    { escape: true }
                );
            }
        </script>
        <apex:form id="form">
            <!-- Search Filter-->
            <div class="lookup">
                <div class="bPageTitle">
                    <div class="ptBody secondaryPalette">
                        <div class="content">
                            <img src="/img/s.gif" alt="" class="pageTitleIcon" title="" />
                            <h1>Lookup</h1>
                        </div>
                    </div>
                </div>
                <div class="pBody">
                    <label class="assistiveText" for="lksrch">Search</label>
                    <apex:inputText id="lksrch" html-placeholder="{!PIPL_Search_Contact_Label}" value="{!searchKeyWord}" />
                    <input value=" Go! " type="Button"  onclick="searchAWSContact()" styleClass="btn" />
                    <div class="bDescription">You can use "*" as a wildcard next to other characters to improve your search results.
                    </div>
                </div>
            </div>
            <div id="QueryResult">
            </div>
        </apex:form>
    </body>
</apex:page>
force-app/main/default/pages/SearchContactPage.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>SearchContactPage</label>
</ApexPage>
force-app/main/default/pages/SearchLeadPage.page
New file
@@ -0,0 +1,185 @@
<apex:page controller="SearchLeadController" showHeader="false" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <head>
    </head>
    <style>
        /* 1. 定义表单样式 To Do Later*/
        table {
            border-collapse: collapse;
            border-spacing: 0;
            width: 98%;
            margin-left: 5px;
        }
    </style>
    <body id="body" class="lookupTab">
        <script type="text/javascript">
            var staticResources = JSON.parse('{!staticResource}');
            var leadAWSIds = JSON.parse('{!leadAWSIds}');
            var leadsInfo = JSON.parse('{!leadsInfo}');
            var searchContactName = '';
            queryLeadFromAWS();
            function searchAWSContact(){
                console.log('Search process!');
                //1. reset table;
                resetTable();
                //2. get contact name value
                searchContactName = document.getElementById('page:form:lksrch').value;
                queryLeadFromAWS();
            }
            function resetTable(){
                let queryResult = document.getElementById('QueryResult');
                let table = document.getElementById('table');
                if(table){
                    queryResult.removeChild(table);
                }
            }
            function preparePayloadForSearchLead(){
                let searchPayload = new Object();
                searchPayload.dataIds = leadAWSIds;
                searchPayload.contactName = searchContactName;
                return JSON.stringify(searchPayload);
            }
            function queryLeadFromAWS() {
                //1. Prepare the payload for contact search
                let requestSearchPayload = preparePayloadForSearchLead();
                console.log('request payload body:'+requestSearchPayload);
                //2. Invoke AWS Service
                fetch(staticResources.searchUrl, {
                    method: 'POST',
                    body: requestSearchPayload,
                    headers: {
                        'Content-Type': 'application/json',
                        'pi-token': staticResources.token
                    }
                }).then((data) => {
                    return data.json();
                }).then((result) => {
                    if(result.object&&result.object.length>0){
                        initContactTable(result);
                    }
                })
            }
            function redirectToParentPage(obj) {
                var winMain = window.opener;
                if (null == winMain) {
                    winMain = window.parent.opener;
                }
                let value = obj.currentTarget.innerText;
                let leadInfo = new Object();
                leadInfo.Name = obj.currentTarget.innerText;
                leadInfo.LeadId = obj.currentTarget.id;
                var selectedContactNode = winMain.document.getElementById('{!JSENCODE($CurrentPage.parameters.leadId)}');
                selectedContactNode.value = JSON.stringify(leadInfo);
                closeWindow();
            }
            function closeWindow() {
                var winMain = window.opener;
                if (null == winMain) {
                    winMain = window.parent.opener;
                }
                winMain.closeLeadPopupWindow();
                window.close();
            }
            function refreshTable(cols,contactInfoList){
                let myTableDiv = document.getElementById("QueryResult");
                let table = document.createElement('TABLE');
                table.border = '1';
                table.id = 'table'
                let tableBody = document.createElement('TBODY');
                table.appendChild(tableBody);
                let headerTR = document.createElement('TR');
                tableBody.appendChild(headerTR);
                for (let i = 0; i < cols.length; i++) {
                    let td = document.createElement('TH');
                    td.width = '75';
                    td.appendChild(document.createTextNode(cols[i]));
                    headerTR.appendChild(td);
                }
                //3. Init the AWS data
                for (let i = 0; i < contactInfoList.length; i++) {
                    let tr = document.createElement('TR');
                    tableBody.appendChild(tr);
                    let contactInfoTemp = contactInfoList[i]
                    for (let j = 0; j < cols.length; j++) {
                        let td = document.createElement('TD');
                        td.width = '75';
                        if(j == 0){
                            td.id = leadsInfo[contactInfoTemp.AWSDataId].Id;
                        }
                        td.appendChild(document.createTextNode(contactInfoTemp[cols[j]]));
                        if (cols[j] == 'Name') {
                            td.addEventListener("click", function (obj) {
                                redirectToParentPage(obj);
                            });
                        }
                        tr.appendChild(td);
                    }
                }
                myTableDiv.appendChild(table);
            }
            function initContactTable(data) {
                let cols = ['Name', 'Email', 'Phone'];
                let contactInfoList = [];
                let awsDataIds = [];
                for(var i=0;i<data.object.length;i++){
                    if(data.object[i].dataId){
                        let contactInfo = new Object();
                        contactInfo.Name = data.object[i].lastName;
                        contactInfo.Email = data.object[i].email;
                        contactInfo.Phone = data.object[i].phone;
                        contactInfo.AWSDataId = data.object[i].dataId;
                        awsDataIds.push(contactInfo.AWSDataId);
                        contactInfo.sfRecordId = '';
                        contactInfoList.push(contactInfo);
                    }
                }
                let AWSIdToSFIdMapValue = {};
                console.log(awsDataIds);
                //Invoke SF BackEnd
                Visualforce.remoting.Manager.invokeAction(
                    '{!$RemoteAction.SearchLeadController.searchLeads}',
                    JSON.stringify(awsDataIds),
                    function (result, event) {
                        if(event.status){
                            if(result.status = 'success'){
                                leadsInfo = JSON.parse(result.message.replace(/(&quot\;)/g,"\""));
                                refreshTable(cols,contactInfoList);
                            }else{
                                console.log('No result');
                            }
                        }
                    },
                    { escape: true }
                );
            }
        </script>
        <apex:form id="form">
            <!-- Search Filter-->
            <div class="lookup">
                <div class="bPageTitle">
                    <div class="ptBody secondaryPalette">
                        <div class="content">
                            <img src="/img/s.gif" alt="" class="pageTitleIcon" title="" />
                            <h1>Lookup</h1>
                        </div>
                    </div>
                </div>
                <div class="pBody">
                    <label class="assistiveText" for="lksrch">Search</label>
                    <apex:inputText id="lksrch" html-placeholder="{!PIPL_Search_Contact_Label}" value="{!searchKeyWord}" />
                    <input value=" Go! " type="Button"  onclick="searchAWSContact()" styleClass="btn" />
                    <div class="bDescription">You can use "*" as a wildcard next to other characters to improve your search results.
                    </div>
                </div>
            </div>
            <div id="QueryResult">
            </div>
        </apex:form>
    </body>
</apex:page>
force-app/main/default/pages/SearchLeadPage.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>SearchLeadPage</label>
</ApexPage>
force-app/main/default/pages/TenderInformationUploadPdf.page
New file
@@ -0,0 +1,190 @@
<!-- 该页面用于Lead对象上传PDF,未来如果要添加其他对象的上传PDF功能,复制该页面,将**standardController**修改为其他对象API名称即可 -->
<apex:page standardController="Tender_information__c" extensions="FileUploadController" id="page" lightningStyleSheets="true">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script>
        var staticResources = JSON.parse('{!staticResource}');
        var parentId = '{!parentId}';
        var uploadUrl = staticResources.newUrl;
        var key;
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:theForm:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'message errorM3';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:theForm:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        function getFileContent(event) {
            var fileObject = document.getElementById("page:theForm:block:uploadSection:file");
            var reader = new FileReader();
            var data = reader.readAsDataURL(fileObject.files[0]);
            debugger
            console.log(event);
        }
        function getBase64(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = () => resolve(reader.result);
                reader.onerror = error => reject(error);
            });
        }
        function disableButtonStatus() {
            let btnNode = document.getElementById('uploadFileId');
            btnNode.classList.add("btnDisabled");
        }
        function enableButtonStatus() {
            let btnNode = document.getElementById('uploadFileId');
            btnNode.classList.remove("btnDisabled");
        }
        function uploadFile() {
            disableButtonStatus();
            var fileObject = document.getElementById("file").files[0];
            getBase64(fileObject).then(
                data => {
                    console.log(data);
                    uploadFileToAWS(data, (fileObject.size).toString(), fileObject.name);
                }
            );
        }
        function confirmTrans(transId, isSuccess) {
            fetch(staticResources.updateUrl, {
                method: 'POST',
                body: JSON.stringify({ 'txId': transId, "isSuccess": isSuccess }),
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then(data => {
                console.log("confirmTrans-" + JSON.stringify(data));
                document.getElementById("file").files[0].name = '';
                enableButtonStatus();
                refreshFiles();
                return data.status;
            })
        }
        function calculateFileSize(fileObject) {
            if (fileObject.size > 20971520) {
                alertErrorMessage('文件过大,请选择小于20mb的文件');
            }
        }
        function uploadFileToAWS(data, size, fileName) {
            console.log("body=" + JSON.stringify({ 'file': data, "size": size, 'fileName': fileName }));
            fetch(uploadUrl, {
                method: 'POST',
                body: JSON.stringify({ 'file': data, "size": size, 'fileName': fileName }),
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then(result => {
                console.log("result" + JSON.stringify(result));
                if (result.success == true) {
                    key = result.object;
                    Visualforce.remoting.Manager.invokeAction(
                        '{!$RemoteAction.FileUploadController.saveFile}',
                        fileName, key, result.txId, parentId,
                        function (resultvalue, event) {
                            //2. show file list
                            if (resultvalue.status == 'fail') {
                                alertErrorMessage(resultvalue.message);
                                //1. Confirm trans
                                confirmTrans(result.txId, 0);
                            } else {
                                alertErrorMessage('上传成功');
                                confirmTrans(result.txId, 1);
                            }
                            // window.location.reload();
                        },
                        { escape: true }
                    );
                    console.log('key' + key);
                } else {
                    alertErrorMessage('上传失败请稍后再试!');
                }
            }).catch((error) => {
                console.error('Error:', error);
            })
            debugger
        }
        function downPdf(fileUrl) {
            window.open(fileUrl,'_blank');
        }
    </script>
    <style>
        .pdf .num {
            width: 30%;
        }
        .pdf.name {
            width: 30%
        }
        .pdf.downLink {
            width: 40%
        }
    </style>
    <apex:form id="theForm">
        <apex:actionFunction name="refreshFiles" action="{!refreshFiles}" reRender="pdf,uploadSection"/>
        <br/>
        <br/>
        <apex:pageBlock id="block">
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <apex:pageBlockSection id="uploadSection">
                <!-- <apex:inputFile id="file" value="{!documentData.body}" filename="{!documentData.name}" /> -->
                <input type="file" id="file" name="filename"/>
                <input class="btn" id='uploadFileId' type="Button" value="确认上传" onclick="uploadFile()" />
            </apex:pageBlockSection>
        </apex:pageBlock>
        <apex:pageBlock title="PDF列表" id="pdf">
            <!-- <apex:pageBlockSection > -->
            <!-- show uploated file list -->
            <apex:pageBlockTable value="{!fileList}" var="file" align="center" columns="3" columnsWidth="30%,30%,40%">
                <apex:column id="name" headerValue="文件名称">
                    <apex:outputLink value="/{!file.Id}" target="_blank">{!file.FileName__c}</apex:outputLink>
                </apex:column>
                <!-- <apex:column id="num" headerValue="父记录链接">
                    <apex:outputLink value="/{!file.ParentRecordId__c}" target="_blank">{!file.ParentRecordId__c}</apex:outputLink>
                </apex:column> -->
                <apex:column id="previewLink" headerValue="预览链接">
                    <apex:outputLink value="{!file.ViewLink__c}" target="{!file.ViewLink__c}">预览链接
                    </apex:outputLink>
                </apex:column>
                <apex:column id="downLink" headerValue="下载链接">
                    <!-- <apex:outputLink value= "{!file.DownloadLink__c}" target="{!file.DownloadLink__c}">下载链接
                    </apex:outputLink> -->
                    <input class="btn" id='downloadFileButton' type="Button" value="下载" onclick="downPdf('{!file.DownloadLink__c}')" />
                </apex:column>
            </apex:pageBlockTable>
            <!-- </apex:pageBlockSection> -->
        </apex:pageBlock>
    </apex:form>
</apex:page>
force-app/main/default/pages/TenderInformationUploadPdf.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>TenderInformationUploadPdf</label>
</ApexPage>
force-app/main/default/pages/TestClass.page
New file
@@ -0,0 +1,2 @@
<apex:page >
</apex:page>
force-app/main/default/pages/TestClass.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>TestClass</label>
</ApexPage>
force-app/main/default/pages/TestVfPage.page
New file
@@ -0,0 +1,3 @@
<apex:page id="page" sidebar="false" showHeader="false"  standardController="Inquiry_form__c" extensions="TestController">
    {!LookUpOverrideFieldsMapJson}
</apex:page>
force-app/main/default/pages/TestVfPage.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>TestVfPage</label>
</ApexPage>
force-app/main/default/pages/UploadPdf.page
New file
@@ -0,0 +1,190 @@
<!-- 该页面用于Lead对象上传PDF,未来如果要添加其他对象的上传PDF功能,复制该页面,将**standardController**修改为其他对象API名称即可 -->
<apex:page standardController="Lead" extensions="FileUploadController" id="page" lightningStyleSheets="true">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <script>
        var staticResources = JSON.parse('{!staticResource}');
        var parentId = '{!parentId}';
        var uploadUrl = staticResources.newUrl;
        var key;
        function alertErrorMessage(errorMsg) {
            let errorMsgNode = document.getElementById("page:theForm:block:msgContent");
            errorMsgNode.innerText = errorMsg;
            errorMsgNode.className = 'message errorM3';
        }
        function hiddenErrorMsgNode() {
            let errorMsgNode = document.getElementById("page:theForm:block:msgContent");
            errorMsgNode.innerText = '';
            errorMsgNode.className = '';
        }
        function getFileContent(event) {
            var fileObject = document.getElementById("page:theForm:block:uploadSection:file");
            var reader = new FileReader();
            var data = reader.readAsDataURL(fileObject.files[0]);
            debugger
            console.log(event);
        }
        function getBase64(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = () => resolve(reader.result);
                reader.onerror = error => reject(error);
            });
        }
        function disableButtonStatus() {
            let btnNode = document.getElementById('uploadFileId');
            btnNode.classList.add("btnDisabled");
        }
        function enableButtonStatus() {
            let btnNode = document.getElementById('uploadFileId');
            btnNode.classList.remove("btnDisabled");
        }
        function uploadFile() {
            disableButtonStatus();
            var fileObject = document.getElementById("file").files[0];
            getBase64(fileObject).then(
                data => {
                    console.log(data);
                    uploadFileToAWS(data, (fileObject.size).toString(), fileObject.name);
                }
            );
        }
        function confirmTrans(transId, isSuccess) {
            fetch(staticResources.updateUrl, {
                method: 'POST',
                body: JSON.stringify({ 'txId': transId, "isSuccess": isSuccess }),
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then(data => {
                console.log("confirmTrans-" + JSON.stringify(data));
                document.getElementById("file").files[0].name = '';
                enableButtonStatus();
                refreshFiles();
                return data.status;
            })
        }
        function calculateFileSize(fileObject) {
            if (fileObject.size > 20971520) {
                alertErrorMessage('文件过大,请选择小于20mb的文件');
            }
        }
        function uploadFileToAWS(data, size, fileName) {
            console.log("body=" + JSON.stringify({ 'file': data, "size": size, 'fileName': fileName }));
            fetch(uploadUrl, {
                method: 'POST',
                body: JSON.stringify({ 'file': data, "size": size, 'fileName': fileName }),
                headers: {
                    'Content-Type': 'application/json',
                    'pi-token': staticResources.token
                }
            }).then((data) => {
                return data.json();
            }).then(result => {
                console.log("result" + JSON.stringify(result));
                if (result.success == true) {
                    key = result.object;
                    Visualforce.remoting.Manager.invokeAction(
                        '{!$RemoteAction.FileUploadController.saveFile}',
                        fileName, key, result.txId, parentId,
                        function (resultvalue, event) {
                            //2. show file list
                            if (resultvalue.status == 'fail') {
                                alertErrorMessage(resultvalue.message);
                                //1. Confirm trans
                                confirmTrans(result.txId, 0);
                            } else {
                                alertErrorMessage('上传成功');
                                confirmTrans(result.txId, 1);
                            }
                            // window.location.reload();
                        },
                        { escape: true }
                    );
                    console.log('key' + key);
                } else {
                    alertErrorMessage('上传失败请稍后再试!');
                }
            }).catch((error) => {
                console.error('Error:', error);
            })
            debugger
        }
        function downPdf(fileUrl) {
            window.open(fileUrl,'_blank');
        }
    </script>
    <style>
        .pdf .num {
            width: 30%;
        }
        .pdf.name {
            width: 30%
        }
        .pdf.downLink {
            width: 40%
        }
    </style>
    <apex:form id="theForm">
        <apex:actionFunction name="refreshFiles" action="{!refreshFiles}" reRender="pdf,uploadSection"/>
        <br/>
        <br/>
        <apex:pageBlock id="block">
            <div style="text-align: center;">
                <apex:outputPanel id="errorMsg">
                    <apex:pageMessages id="msgContent" escape="false" />
                </apex:outputPanel>
            </div>
            <apex:pageBlockSection id="uploadSection">
                <!-- <apex:inputFile id="file" value="{!documentData.body}" filename="{!documentData.name}" /> -->
                <input type="file" id="file" name="filename"/>
                <input class="btn" id='uploadFileId' type="Button" value="确认上传" onclick="uploadFile()" />
            </apex:pageBlockSection>
        </apex:pageBlock>
        <apex:pageBlock title="PDF列表" id="pdf">
            <!-- <apex:pageBlockSection > -->
            <!-- show uploated file list -->
            <apex:pageBlockTable value="{!fileList}" var="file" align="center" columns="3" columnsWidth="30%,30%,40%">
                <apex:column id="name" headerValue="文件名称">
                    <apex:outputLink value="/{!file.Id}" target="_blank">{!file.FileName__c}</apex:outputLink>
                </apex:column>
                <!-- <apex:column id="num" headerValue="父记录链接">
                    <apex:outputLink value="/{!file.ParentRecordId__c}" target="_blank">{!file.ParentRecordId__c}</apex:outputLink>
                </apex:column> -->
                <apex:column id="previewLink" headerValue="预览链接">
                    <apex:outputLink value="{!file.ViewLink__c}" target="{!file.ViewLink__c}">预览链接
                    </apex:outputLink>
                </apex:column>
                <apex:column id="downLink" headerValue="下载链接">
                    <!-- <apex:outputLink value= "{!file.DownloadLink__c}" target="{!file.DownloadLink__c}">下载链接
                    </apex:outputLink> -->
                    <input class="btn" id='downloadFileButton' type="Button" value="下载" onclick="downPdf('{!file.DownloadLink__c}')" />
                </apex:column>
            </apex:pageBlockTable>
            <!-- </apex:pageBlockSection> -->
        </apex:pageBlock>
    </apex:form>
</apex:page>
force-app/main/default/pages/UploadPdf.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>UploadPdf</label>
</ApexPage>
force-app/main/default/pages/ViewASEActivityDecryptInfo.page
New file
@@ -0,0 +1,85 @@
<apex:page standardController="ASEActivity__c" extensions="NewAndEditASEActivityController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!ASEActivity__c[encryptedAPI]}" />
                </apex:repeat>
                <apex:outputField html-data-id="ReporterASE__c}" title="{!ApiPrefix}ReporterASE__c" value="{!ASEActivity__c['ReporterASE__c']}" />
            </apex:pageBlockSection>
            <script>
                var config = {
                    SobjectName : "{!SobjectName}",
                    ApiPrefix:"{!ApiPrefix}",
                    AWSToSobjectMap:{!AWSToSobjectMapJson},
                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                };
                var staticResources = JSON.parse('{!staticResource}');
                var staticResourcesContact = JSON.parse('{!staticResourceContact}');
                function QuerySobjectFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                function QueryContactFromAWS() {
                    if('{!contactAWS}' != null && '{!contactAWS}' != ''){
                        console.log('staticResourcesContact .queryUrl' + staticResourcesContact .queryUrl);
                        AWSService.query(staticResourcesContact .queryUrl, '{!contactAWS}', queryContactBack, staticResources.token);
                    }
                }
                var queryContactBack = function queryContactBack(data){
                    if(!data.object){
                        console.log('data.object is ' + data.object);
                        return;
                    }
                    let t = "[title='"+config.ApiPrefix+"ReporterASE__c']";
                    let ele = document.querySelector(t);
                    ele.innerHTML = data.object.lastName;
                    ele.title='';
                }
                function QuerySobjectFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    if(!data.object){
                        console.log('data.object is ' + data.object);
                        return;
                    }
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
                        let ele = document.querySelector(t);
                        console.log(ele);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                    // 当不能自动正确替换加密数据时需要在此处添加js,硬编码处理
                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QuerySobjectFromAWS();
                    QueryContactFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewASEActivityDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewASEActivityDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewAddressDecryptInfo.page
New file
@@ -0,0 +1,32 @@
<apex:page standardController="Address__c" extensions="NewAndEditAddressController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!Address__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                // AWSService.sfSessionId = '{!GETSESSIONID()}';
                var staticResources = JSON.parse('{!staticResource}');
                function QueryAddressFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id1:0:j_id2']").innerHTML = data.object.telephone;
                    document.querySelector("[data-id='ZipCode__c']").innerHTML = data.object.zipCode;
                    document.querySelector("[data-id='Detailed_Address__c']").innerHTML = data.object.detailedAddress;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QueryAddressFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewAddressDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewAddressDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewAgencyContactDecryptInfo.page
New file
@@ -0,0 +1,56 @@
<apex:page standardController="Agency_Contact__c" extensions="NewAndEditAgencyContactController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Agency_Contact__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var config = {
                    SobjectName : "{!SobjectName}",
                    ApiPrefix:"{!ApiPrefix}",
                    AWSToSobjectMap:{!AWSToSobjectMapJson},
                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                };
                var staticResources = JSON.parse('{!staticResource}');
                function QuerySobjectFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    if(!data.object){
                        console.log('data.object is ' + data.object);
                        return;
                    }
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
                        let ele = document.querySelector(t);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                    // 当不能自动正确替换加密数据时需要在此处添加js,硬编码处理
                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QuerySobjectFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewAgencyContactDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewAgencyContactDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewCaseDecryptInfo.page
New file
@@ -0,0 +1,30 @@
<apex:page standardController="Case" extensions="NewAndEditCaseController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!Case[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var staticResources = JSON.parse('{!staticResource}');
                function QueryCaseFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id1:0:j_id2']").innerHTML = data.object.cicTelephone;
                    document.querySelector("[data-id='CASE_CUSTOMER__c']").innerHTML = data.object.caseCustomer;
                    document.querySelector("[data-id='Customer_manual__c']").innerHTML = data.object.customerManual;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QueryCaseFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewCaseDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewCaseDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewConsumApplyEquipmentSetDetailDecrypt.page
New file
@@ -0,0 +1,26 @@
<apex:page standardController="Consum_Apply_Equipment_Set_Detail__c" extensions="NewConsumApplyEquipSetDetailController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!Consum_Apply_Equipment_Set_Detail__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var staticResources = JSON.parse('{!staticResource}');
                function QueryConsumApplyFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id1:0:j_id2']").innerHTML = data.object.trialUser;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue');
                    QueryConsumApplyFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewConsumApplyEquipmentSetDetailDecrypt.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewConsumApplyEquipmentSetDetailDecrypt</label>
</ApexPage>
force-app/main/default/pages/ViewContactDecryptInfo.page
New file
@@ -0,0 +1,68 @@
<apex:page standardController="Contact" extensions="NewAndEditContactController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Contact[encryptedAPI]}" />
                </apex:repeat>
                <apex:outputText label="统一用户Id" id="viewContactId"  value="" />
            </apex:pageBlockSection>
            <script>
                var config = {
                    SobjectName : "{!SobjectName}",
                    ApiPrefix:"{!ApiPrefix}",
                    AWSToSobjectMap:{!AWSToSobjectMapJson},
                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                };
                var staticResources = JSON.parse('{!staticResource}');
                console.log(staticResources)
                function QuerySobjectFromAWS() {
                    console.log('AWSDataId:'+'{!AWSDataId}')
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                    //查找viewContactId
                    AWSService.query(staticResources.viewUnifiedContactUrl, '{!unifiedIContactID}', queryBackContactId, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    if(!data.object){
                        console.log('data.object is ' + data.object);
                        return;
                    }
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
                        let ele = document.querySelector(t);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                    // 当不能自动正确替换加密数据时需要在此处添加js,硬编码处理
                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                };
                var queryBackContactId = function queryBackContactId(data) {
                    console.log('queryBackContactId:')
                    console.log(JSON.stringify(data))
                    if(data.status == '0'){
                        document.getElementById('page:form:pageBlock:pageBlockSection:viewContactId').innerText = data.object.viewContactId;
                    }
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QuerySobjectFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewContactDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewContactDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewDecryptConsumApply.page
New file
@@ -0,0 +1,27 @@
<apex:page standardController="Consum_Apply__c" extensions="NewConsumApplyController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!Consum_Apply__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var staticResources = JSON.parse('{!staticResource}');
                function QueryConsumApplyFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id1:0:j_id2']").innerHTML = data.object.phoneNumber;
                    document.querySelector("[data-id='direct_shippment_address__c']").innerHTML = data.object.directShippmentAddress;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue');
                    QueryConsumApplyFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewDecryptConsumApply.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewDecryptConsumApply</label>
</ApexPage>
force-app/main/default/pages/ViewEventDecryptInfo.page
New file
@@ -0,0 +1,93 @@
<apex:page standardController="Event" extensions="NewAndEditEventController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Event[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                // var config = {
                //     SobjectName : "{!SobjectName}",
                //     ApiPrefix:"{!ApiPrefix}",
                //     AWSToSobjectMap:{!AWSToSobjectMapJson},
                //     AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
                //     AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                // };
                AWSService.sfSessionId = '{!GETSESSIONID()}';
                var staticResources = JSON.parse('{!staticResources}');
                var contactAWSIds = JSON.parse('{!contactAWSIds}'); //AWS ContactId
                var sfIdToContactInfo = {};
                function preparePayloadForSearchContact(){
                    let searchPayload = new Object();
                    searchPayload.dataIds = contactAWSIds;
                    searchPayload.contactName = '';
                    console.log('searchPayload: ' + JSON.stringify(searchPayload));
                    return JSON.stringify(searchPayload);
                }
                function searchContactAll(){
                    let data = preparePayloadForSearchContact();
                    let searchCallBack = function searchCallBack(result){
                        let contacts = result.object;
                        console.log('contacts: ' + contacts);
                        if(contacts == null){
                            return;
                        }
                        //赋值给前端页面
                        for(var i=0;i<contacts.length;i++){
                            // let temp = {}
                            // temp.lastName = contacts[i].lastName?contacts[i].lastName:'';
                            // console.log('temp.lastName: ' + temp.lastName);
                            console.log('contacts[i].lastName?contacts[i].lastName:' + contacts[i].lastName?contacts[i].lastName:'');
                            document.querySelector("[data-id='Visitor" + (i + 1) + "__c']").innerHTML = contacts[i].lastName?contacts[i].lastName:'';
                        //     if(contacts[i].sfRecordId){
                        //         sfIdToContactInfo[contacts[i].sfRecordId] = temp;
                        //     }
                        }
                        // console.log('AWS Result:' + JSON.stringify(sfIdToContactInfo));
                    };
                    AWSService.search(staticResources.searchUrl,data,searchCallBack,staticResources.token);
                }
                // function QuerySobjectFromAWS() {
                //     AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                // }
                // var queryBack = function queryBack(data) {
                //     if(!data.object){
                //         console.log('data.object is ' + data.object);
                //         return;
                //     }
                //     for(let f in config.AWSToSobjectNonEncryptedMap){
                //         let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
                //         let ele = document.querySelector(t);
                //         if(ele){
                //             ele.title = '';
                //             if(data.object.hasOwnProperty(f)){
                //                 ele.innerHTML = data.object[f];
                //             }
                //             else{
                //                 console.log(f + 'is not in data.object');
                //             }
                //         }else{
                //             console.log('selector='+t+' not found');
                //         }
                //     }
                //     // 当不能自动正确替换加密数据时需要在此处添加js,硬编码处理
                //     // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                // };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    //QuerySobjectFromAWS();
                    searchContactAll();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewEventDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewEventDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewInquiryFormDecryptInfo.page
New file
@@ -0,0 +1,56 @@
<apex:page standardController="Inquiry_form__c" extensions="NewAndEditInquiryFormController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Inquiry_form__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var config = {
                    SobjectName : "{!SobjectName}",
                    ApiPrefix:"{!ApiPrefix}",
                    AWSToSobjectMap:{!AWSToSobjectMapJson},
                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                };
                var staticResources = JSON.parse('{!staticResource}');
                function QuerySobjectFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    if(!data.object){
                        console.log('data.object is ' + data.object);
                        return;
                    }
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
                        let ele = document.querySelector(t);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                    // 当不能自动正确替换加密数据时需要在此处添加js,硬编码处理
                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QuerySobjectFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewInquiryFormDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewInquiryFormDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewInspectionReportDecryptInfo.page
New file
@@ -0,0 +1,56 @@
<apex:page standardController="Inspection_Report__c" extensions="NewAndEditInspectionReportController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Inspection_Report__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var config = {
                    SobjectName : "{!SobjectName}",
                    ApiPrefix:"{!ApiPrefix}",
                    AWSToSobjectMap:{!AWSToSobjectMapJson},
                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                };
                var staticResources = JSON.parse('{!staticResource}');
                function QuerySobjectFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    if(!data.object){
                        console.log('data.object is ' + data.object);
                        return;
                    }
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
                        let ele = document.querySelector(t);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                    // 当不能自动正确替换加密数据时需要在此处添加js,硬编码处理
                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QuerySobjectFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewInspectionReportDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>53.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewInspectionReportDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewLeadDecryptInfo.page
New file
@@ -0,0 +1,32 @@
<apex:page standardController="Lead" extensions="NewAndEditLeadController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!Lead[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                AWSService.sfSessionId = '{!GETSESSIONID()}';
                var staticResources = JSON.parse('{!staticResource}');
                function QueryLeadFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    document.querySelector("[data-id='LastName']").innerHTML = data.object.lastName;
                    document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id2:0:j_id3']").innerHTML =  data.object.phone;
                    document.querySelector("[data-id='Email']").innerHTML = data.object.email;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QueryLeadFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewLeadDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewLeadDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewListOfConsumablesDecrypt.page
New file
@@ -0,0 +1,2 @@
<apex:page >
</apex:page>
force-app/main/default/pages/ViewListOfConsumablesDecrypt.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewListOfConsumablesDecrypt</label>
</ApexPage>
force-app/main/default/pages/ViewOnCallDecrypt.page
New file
@@ -0,0 +1,27 @@
<apex:page standardController="On_Call__c" extensions="OnCallController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!On_Call__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var staticResources = JSON.parse('{!staticResource}');
                function QueryConsumApplyFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id1:0:j_id2']").innerHTML = data.object.callerPhone;
                    document.querySelector("[data-id='Responsible_Person_HP__c']").innerHTML = data.object.responsiblePersonHP;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue');
                    QueryConsumApplyFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewOnCallDecrypt.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewOnCallDecrypt</label>
</ApexPage>
force-app/main/default/pages/ViewParticipantsDecryptInfo.page
New file
@@ -0,0 +1,28 @@
<apex:page standardController="CampaignMember__c" extensions="ViewParticipantsController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <apex:outputText label="统一用户Id" id="viewContactId"  value="" />
            </apex:pageBlockSection>
            <script>
                var staticResources = JSON.parse('{!staticResourceContact}');
                console.log(staticResources)
                function QuerySobjectFromAWS() {
                    //查找viewContactId
                    AWSService.query(staticResources.viewUnifiedContactUrl, '948578480969220097', queryBackContactId, staticResources.token);
                }
                var queryBackContactId = function queryBackContactId(data) {
                    console.log(JSON.stringify(data))
                    if(data.status == '0'){
                        document.getElementById('page:form:pageBlock:pageBlockSection:viewContactId').innerText = data.object.viewContactId;
                    }
                };
                sfdcPage.appendToOnloadQueue(function () {
                    QuerySobjectFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewParticipantsDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewParticipantsDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewQISReportDecryptInfo.page
New file
@@ -0,0 +1,65 @@
<apex:page standardController="QIS_Report__c" extensions="NewAndEditQISController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!QIS_Report__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var config = {
                    SobjectName : "{!SobjectName}",
                    ApiPrefix:"{!ApiPrefix}",
                    AWSToSobjectMap:{!AWSToSobjectMapJson},
                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                };
                var staticResources = JSON.parse('{!staticResource}');
                function QuerySobjectFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    for(let f in config.AWSToSobjectMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectMap[f]+"']";
                        let ele = document.querySelector(t);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                    for(let f in config.AWSToSobjectEncryptedMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectMap[f]+"']";
                        let ele = document.querySelector(t);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    QuerySobjectFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewQISReportDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewQISReportDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewRentalApplyDecrypt.page
New file
@@ -0,0 +1,27 @@
<apex:page standardController="Rental_Apply__c" extensions="RentalApplyController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!Rental_Apply__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var staticResources = JSON.parse('{!staticResource}');
                function QueryConsumApplyFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id1:1:j_id2']").innerHTML = data.object.phoneNumber;
                    document.querySelector("[data-id='direct_shippment_address__c']").innerHTML = data.object.directShippmentAddress;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue');
                    QueryConsumApplyFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewRentalApplyDecrypt.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewRentalApplyDecrypt</label>
</ApexPage>
force-app/main/default/pages/ViewRepairEncrypt.page
New file
@@ -0,0 +1,47 @@
<apex:page standardController="Repair__c" extensions="NewRepairController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!Repair__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                debugger;
                var staticResources = JSON.parse('{!staticResource}');
                var staticResourceContact = JSON.parse('{!staticResourceContact}');
                var staticResourceAddress = JSON.parse('{!staticResourceAddress}');
                function QueryConsumApplyFromAWS() {
                        AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    console.log(data);
                    document.querySelector("[data-id='address_Contacts__c']").innerHTML = data.object.addressContacts;
                    document.querySelector("[data-id='address_Contacts_Name__c']").innerHTML = data.object.addressContactsName;
                    document.querySelector("[data-id='address_Telephone__c']").innerHTML = data.object.addressTelephone;
                    document.querySelector("[data-id='address_ZipCode__c']").innerHTML = data.object.addressZipCode;
                    document.querySelector("[data-id='Detailed_Address__c']").innerHTML = data.object.detailedAddress;
                    document.querySelector("[data-id='RepairApplicant__c']").innerHTML = data.object.repairApplicant;
                    AWSService.query(staticResourceAddress.queryUrl, '{!DecryptAWSDataId}', queryBackDecrypt, staticResourceAddress.token);
                };
                var queryBackContact = function queryBack(data) {
                    console.log(data);
                    document.querySelector("[data-id='address_Contacts__c']").innerHTML = data.object.lastName;
                };
                var queryBackDecrypt = function queryBack(data) {
                    document.querySelector("[data-id='Detailed_Address__c']").innerHTML = data.object.detailedAddress;
                    document.querySelector("[data-id='address_ZipCode__c']").innerHTML = data.object.zipCode;
                    document.querySelector("[data-id='address_Telephone__c']").innerHTML = data.object.telephone;
                    AWSService.query(staticResourceContact.queryUrl, '{!ContactAWSDataId}', queryBackContact, staticResourceContact.token);
                }
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue');
                    debugger;
                    QueryConsumApplyFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewRepairEncrypt.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewRepairEncrypt</label>
</ApexPage>
force-app/main/default/pages/ViewRepairSubOrderDecryptInfo.page
New file
@@ -0,0 +1,56 @@
<apex:page standardController="RepairSubOrder__c" extensions="NewAndEditRepairSubOrderController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!RepairSubOrder__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var config = {
                    SobjectName : "{!SobjectName}",
                    ApiPrefix:"{!ApiPrefix}",
                    AWSToSobjectMap:{!AWSToSobjectMapJson},
                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                };
                var staticResources = JSON.parse('{!staticResource}');
                function QuerySobjectFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    if(!data.object){
                        console.log('data.object is ' + data.object);
                        return;
                    }
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
                        let ele = document.querySelector(t);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                    // 当不能自动正确替换加密数据时需要在此处添加js,硬编码处理
                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QuerySobjectFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewRepairSubOrderDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewRepairSubOrderDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewReportDecryptInfo.page
New file
@@ -0,0 +1,40 @@
<apex:page standardController="Report__c" extensions="NewAndEditReportController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!encryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" value="{!Report__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                var staticResources = JSON.parse('{!staticResource}');
                function QueryLeadFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    document.querySelector("[data-id='VOC_Informer_Name__c']").innerHTML=data.object.vocInformerName!=null?data.object.vocInformerName.replace(/"/g,""):'';
                    document.querySelector("[id='page:form:pageBlock:pageBlockSection:j_id1:1:j_id2']").innerHTML=data.object.callerPhone!=null?data.object.callerPhone.replace(/"/g,""):'';
                    document.querySelector("[data-id='VOC_Informer_Contact__c']").innerHTML=data.object.vocInformerContact!=null?data.object.vocInformerContact.replace(/"/g,""):'';
                    document.querySelector("[data-id='Person_In_Charge_Text__c']").innerHTML=data.object.personInChargeText!=null?data.object.personInChargeText.replace(/"/g,""):'';
                    document.querySelector("[data-id='Professor_sigh_text__c']").innerHTML=data.object.professorSighText!=null?data.object.professorSighText.replace(/"/g,""):'';
                    document.querySelector("[data-id='Staff_Info_Manual_c__c']").innerHTML=data.object.staffInfoManual!=null?data.object.staffInfoManual.replace(/"/g,""):'';
                    document.querySelector("[data-id='Responsible_Person_HP_c__c']").innerHTML=data.object.responsiblePersonHP!=null?data.object.responsiblePersonHP.replace(/"/g,""):'';
                    document.querySelector("[data-id='Practitioner1_Part__c']").innerHTML=data.object.practitioner1Part!=null?data.object.practitioner1Part.replace(/"/g,""):'';
                    document.querySelector("[data-id='Practitioner2_Part__c']").innerHTML=data.object.practitioner2Part!=null?data.object.practitioner2Part.replace(/"/g,""):'';
                    document.querySelector("[data-id='Practitioner3_Part__c']").innerHTML=data.object.practitioner3Part!=null?data.object.practitioner3Part.replace(/"/g,""):'';
                    document.querySelector("[data-id='Practitioner4_Part__c']").innerHTML=data.object.practitioner4Part!=null?data.object.practitioner4Part.replace(/"/g,""):'';
                    document.querySelector("[data-id='Practitioner5_Part__c']").innerHTML=data.object.practitioner5Part!=null?data.object.practitioner5Part.replace(/"/g,""):'';
                    document.querySelector("[data-id='age__c']").innerHTML=data.object.age!=null?data.object.age.replace(/"/g,""):'';
                    document.querySelector("[data-id='Medical_History__c']").innerHTML=data.object.medicalHistory!=null?data.object.medicalHistory.replace(/"/g,""):'';
                    document.querySelector("[data-id='sex__c']").innerHTML=data.object.sex!=null?data.object.sex.replace(/"/g,""):'';
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('awsDataId = '+'{!AWSDataId}')
                    QueryLeadFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewReportDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewReportDecryptInfo</label>
</ApexPage>
force-app/main/default/pages/ViewTenderinformationDecryptInfo.page
New file
@@ -0,0 +1,58 @@
<apex:page standardController="Tender_information__c" extensions="NewAndEditTenderinformationController" id="page">
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }"/>
    <script src="../../soap/ajax/53.0/connection.js" type="text/javascript"></script>
    <apex:form id="form">
        <apex:pageblock id="pageBlock">
            <apex:pageBlockSection showHeader="false" title="" collapsible="true" columns="2" id="pageBlockSection">
                <!--Each section has layoutFields, let's iterate them as well-->
                <apex:repeat value="{!layoutEncryptedAPIList}" var="encryptedAPI">
                    <apex:outputField html-data-id="{!encryptedAPI}" title="{!ApiPrefix}{!encryptedAPI}" value="{!Tender_information__c[encryptedAPI]}" />
                </apex:repeat>
            </apex:pageBlockSection>
            <script>
                AWSService.sfSessionId = '{!GETSESSIONID()}';
                var config = {
                    SobjectName : "{!SobjectName}",
                    ApiPrefix:"{!ApiPrefix}",
                    AWSToSobjectMap:{!AWSToSobjectMapJson},
                    AWSToSobjectNonEncryptedMap:{!AWSToSobjectNonEncryptedMapJson},
                    AWSToSobjectEncryptedMap:{!AWSToSobjectEncryptedMapJson}
                };
                var staticResources = JSON.parse('{!staticResource}');
                function QuerySobjectFromAWS() {
                    AWSService.query(staticResources.queryUrl, '{!AWSDataId}', queryBack, staticResources.token);
                }
                var queryBack = function queryBack(data) {
                    if(!data.object){
                        console.log('data.object is ' + data.object);
                        return;
                    }
                    for(let f in config.AWSToSobjectNonEncryptedMap){
                        let t = "[title='"+config.ApiPrefix+config.AWSToSobjectNonEncryptedMap[f]+"']";
                        let ele = document.querySelector(t);
                        if(ele){
                            ele.title = '';
                            if(data.object.hasOwnProperty(f)){
                                ele.innerHTML = data.object[f];
                            }
                            else{
                                console.log(f + 'is not in data.object');
                            }
                        }else{
                            console.log('selector='+t+' not found');
                        }
                    }
                    // 当不能自动正确替换加密数据时需要在此处添加js,硬编码处理
                    // document.querySelector("[data-id='LastName']").value = data.object.lastName;
                };
                sfdcPage.appendToOnloadQueue(function () {
                    console.log('sfdcPage.appendToOnloadQueue')
                    // document.querySelector("[data-id='LastName']").parentNode.parentNode.parentNode.children[0].innerText = '姓名'
                    QuerySobjectFromAWS();
                });
            </script>
        </apex:pageblock>
    </apex:form>
</apex:page>
force-app/main/default/pages/ViewTenderinformationDecryptInfo.page-meta.xml
New file
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexPage xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>54.0</apiVersion>
    <availableInTouch>false</availableInTouch>
    <confirmationTokenRequired>false</confirmationTokenRequired>
    <label>ViewTenderinformationDecryptInfo</label>
</ApexPage>
force-app/main/default/triggers/FileAddressTrigger.trigger
New file
@@ -0,0 +1,13 @@
trigger FileAddressTrigger on FileAddress__c (before delete) {
    List<FileAddress__c> fileAddressList = trigger.old;
    Set<String> deleteFiles = new Set<String>();
    for(FileAddress__c fd:fileAddressList){
        if(String.isNotBlank(fd.AWS_File_Key__c)&&String.isNotEmpty(fd.AWS_File_Key__c)){
            deleteFiles.add(fd.AWS_File_Key__c);
        }
    }
    if(!deleteFiles.isEmpty()){
        system.debug('DeleteFiles Value:'+JSON.serialize(deleteFiles));
        AWSServiceTool.deleteFileAddress(deleteFiles);
    }
}
force-app/main/default/triggers/FileAddressTrigger.trigger-meta.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexTrigger xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <status>Active</status>
</ApexTrigger>