buli
2022-04-15 900c50a247705d6fe8833e84d31b5d51616b7c26
20220415
14个文件已添加
8个文件已修改
1940 ■■■■■ 已修改文件
force-app/main/default/classes/FileUploadController.cls 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/FileUploadController.cls-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NEWCreateSWOQuoteController.cls 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewLoanerApplicationController.cls 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/NewLoanerUserController.cls 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/SBG027TriggerHandleTest.cls 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ContactFileUploadPage.page 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/ContactFileUploadPage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/LoanerUploadFilePage.page 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/LoanerUploadFilePage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NEWCreateSWOQuote.page 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NEWCreateSWOQuoteReadOnly.page 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewLoanerApplication.page 289 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/NewLoanerUser.page 216 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SSBDContractFileUploadPage.page 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SSBDContractFileUploadPage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SWOFileUploadPage.page 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SWOFileUploadPage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SearchAWSContactByNamePage.page 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/pages/SearchAWSContactByNamePage.page-meta.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/triggers/FileAddressTrigger.trigger 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/triggers/FileAddressTrigger.trigger-meta.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
force-app/main/default/classes/FileUploadController.cls
New file
@@ -0,0 +1,69 @@
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');
        // 去除filename里得“&” bysushanhu 20220414
        fileName = fileName.remove('&');
        file.DownloadLink__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,FileAddress__c.ViewLink__c FROM FileAddress__c where ParentRecordId__c=:parentId order by createddate desc];
        }
        return [SELECT Id, ParentRecordId__c,FileName__c,DownloadLink__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/NEWCreateSWOQuoteController.cls
@@ -28,6 +28,10 @@
    public Boolean aftORbef { get; set; }
    public Boolean aftORbef1 { get; set; }
    public String staticResource { get; private set; }// 20220311 PI改造 by Bright
    public String contactstaticResource { get; private set; }// 20220311 PI改造 by Bright
    public NEWCreateSWOQuoteController() {
        swoId = System.currentPageReference().getParameters().get('swoId');
        Id = System.currentPageReference().getParameters().get('Id');
@@ -41,6 +45,9 @@
            baseUrl += '/production';
        }
        rtUrl = System.currentPageReference().getParameters().get('retURL');
        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Quotes__c'));// 20220221 PI改造 by Bright
        contactstaticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));// 20220221 PI改造 by Bright
    }
    public NEWCreateSWOQuoteController(ApexPages.StandardController controller) {
@@ -231,7 +238,9 @@
        if (String.isNotBlank(Id)) {
            List<Quotes__c> quotesList = new List<Quotes__c>();
            quotesList = [SELECT  Id, Name, BILLING_SCHEDULE__c, BILL_TO__c, SHIP_TO__c, BILL_TO_SELECT__c, CATEGORY_1_INDUSTRY_SO__c, CATEGORY_2_USE_SO__c, COLLECTION_STATUS__c, CONTACT_EMAIL__c, CONTACT_FAX__c, CONTACT_NAME__c, CONTACT_PHONE__c, CONTRACT_NAME__c, CURRENCY__c, DATE__c, DISCOUNT_ITEM__c, DISCOUNT_ITEM_F__c, DISCOUNT_WORKFLOW_TYPE__c, EST_EXTENDED_COST__c, EST_GROSS_PROFIT__c, EST_GROSS_PROFIT_PERCENT__c, ESTIMATE__c, EXP_CLOSE__c, EXPIRES__c, FDA_REPORT_COMPLETE__c, GOVERNMENT_ORDER__c, GSA_ORDER__c, INCOTERM__c, INITIATE_APPROVAL_ROUTING__c, INVOICE_MESSAGING__c, IS_SELLER_IMPORTER_OF_RECORD__c, LEAD_SOURCE__c, LEAD_TIME__c, LOCATION__c, NO_CHARGE_TYPE__c, notSaveEmail__c, NSN__c, ONLINE_BILLING__c, ONLINE_BILLING_ADDRESS__c, OPPORTUNITY__c, ORDER_TYPE__c, PKMS_PO_FOR_RECEIPT__c, PO__c, PROBABILITY__c, PRODUCT_SEGMENT__c, QUOTE_TITLE__c, RATE__c, RepairPart__c, REVISION_NEEDED__c, RMA_NOTES__c, COMPANY__c, SALES_TEAM_AUTO_ASSIGNMENT_OVERRIDE__c, SALES_TEAM_AUTO_ASSIGN_ON_SAVE__c, SELECT_MESSAGE__c, SHIPPING_CARRIER__c, SHIPPING_COST__c, SHIPPING_TAX_CODE__c, SHIPPING_TAX_RATE__c, SHIP_TO_ENTITY_USE_CODE__c, SHIP_TO_SELECT__c, SHIP_VIA__c, STATUS__c, SUBSIDIARY__c, SUBTOTAL__c, SWO__c, SWOName__c, SWO_NUMBER__c, SWO_PART_NUMBERS__c, SWO_SERIAL__c, SWOStatus__c, TAX_ID__c, TAX_OVERRIDE__c, TERMS__c, TERMS_OVERRIDE__c, THROW_MESSAGE__c, TOTAL_TRANSACTION_ITEM_WEIGHT_KGS__c, VERTICAL_MARKET_SEGMENT_SO__c, QuotesType__c, CUSTOMER_MESSAGE__c, TOTAL__c, BILL_TO_ENTITY_USE_CODE__c, COMPANYId__c, COMPANYName__c, DISCOUNT_STATUS__c, DISCOUNT_STATUS_ROUTING__c, TAX_CODE__c, TAX_RATE__c, TAX__c, DISCOUNT__c, SWOStatusMark__c  FROM Quotes__c WHERE Id = :Id];
            quotesList = [SELECT  Id,
            AWS_Data_Id__c,CONTACT_NAME__r.Name,CONTACT_NAME__r.AWS_Data_Id__c, // 20220311 PI改造 by Bright
            Name, BILLING_SCHEDULE__c, BILL_TO__c, SHIP_TO__c, BILL_TO_SELECT__c, CATEGORY_1_INDUSTRY_SO__c, CATEGORY_2_USE_SO__c, COLLECTION_STATUS__c, CONTACT_EMAIL__c, CONTACT_FAX__c, CONTACT_NAME__c, CONTACT_PHONE__c, CONTRACT_NAME__c, CURRENCY__c, DATE__c, DISCOUNT_ITEM__c, DISCOUNT_ITEM_F__c, DISCOUNT_WORKFLOW_TYPE__c, EST_EXTENDED_COST__c, EST_GROSS_PROFIT__c, EST_GROSS_PROFIT_PERCENT__c, ESTIMATE__c, EXP_CLOSE__c, EXPIRES__c, FDA_REPORT_COMPLETE__c, GOVERNMENT_ORDER__c, GSA_ORDER__c, INCOTERM__c, INITIATE_APPROVAL_ROUTING__c, INVOICE_MESSAGING__c, IS_SELLER_IMPORTER_OF_RECORD__c, LEAD_SOURCE__c, LEAD_TIME__c, LOCATION__c, NO_CHARGE_TYPE__c, notSaveEmail__c, NSN__c, ONLINE_BILLING__c, ONLINE_BILLING_ADDRESS__c, OPPORTUNITY__c, ORDER_TYPE__c, PKMS_PO_FOR_RECEIPT__c, PO__c, PROBABILITY__c, PRODUCT_SEGMENT__c, QUOTE_TITLE__c, RATE__c, RepairPart__c, REVISION_NEEDED__c, RMA_NOTES__c, COMPANY__c, SALES_TEAM_AUTO_ASSIGNMENT_OVERRIDE__c, SALES_TEAM_AUTO_ASSIGN_ON_SAVE__c, SELECT_MESSAGE__c, SHIPPING_CARRIER__c, SHIPPING_COST__c, SHIPPING_TAX_CODE__c, SHIPPING_TAX_RATE__c, SHIP_TO_ENTITY_USE_CODE__c, SHIP_TO_SELECT__c, SHIP_VIA__c, STATUS__c, SUBSIDIARY__c, SUBTOTAL__c, SWO__c, SWOName__c, SWO_NUMBER__c, SWO_PART_NUMBERS__c, SWO_SERIAL__c, SWOStatus__c, TAX_ID__c, TAX_OVERRIDE__c, TERMS__c, TERMS_OVERRIDE__c, THROW_MESSAGE__c, TOTAL_TRANSACTION_ITEM_WEIGHT_KGS__c, VERTICAL_MARKET_SEGMENT_SO__c, QuotesType__c, CUSTOMER_MESSAGE__c, TOTAL__c, BILL_TO_ENTITY_USE_CODE__c, COMPANYId__c, COMPANYName__c, DISCOUNT_STATUS__c, DISCOUNT_STATUS_ROUTING__c, TAX_CODE__c, TAX_RATE__c, TAX__c, DISCOUNT__c, SWOStatusMark__c  FROM Quotes__c WHERE Id = :Id];
            if (quotesList.size() > 0) {
                QuotesPage = quotesList[0];
            }
@@ -324,7 +333,6 @@
        }
        //首先是从swo创建quotes,有了swoid,就是用新的静态资源显示的免责申明。
        //之后,编辑已经创建完了的quotes,15号之前创建的,显示的是旧的。旧的就是aftORbef==false。
        //当然,aftORbef==false具体指的是旧的也可以指查不到的(还没有存入数据库的,创建时)。
        if (String.isNotBlank(swoId)) {
            aftORbef1 = true;
        }else{
@@ -362,7 +370,7 @@
        if ('维修报价单'.equals(QuotesPage.QuotesType__c)) {
            QuotesPage.CUSTOMER_MESSAGE__c = '';
            //日期2121年11月15号之后的,用新的免责申明。
           if (aftORbef == true || aftORbef1 == true) {
           if (aftORbef == true) {
                QuotesPage.CUSTOMER_MESSAGE__c += '-维修质保只涵盖于本次维修的配件,维修质保期为仪器发货后三个月加八天。\n';
                Messages01 = '-维修质保只涵盖于本次维修的配件,维修质保期为仪器发货后三个月加八天。';
            }else{
@@ -380,13 +388,8 @@
            Messages05 = '日期:';
        } else if ('零件报价单'.equals(QuotesPage.QuotesType__c)) {
            QuotesPage.CUSTOMER_MESSAGE__c = '';
            if ('NDT'.equals(QuotesPage.PRODUCT_SEGMENT__c)) {
                QuotesPage.CUSTOMER_MESSAGE__c += '-仪景通光学科技(上海)有限公司北京分公司售出的维修配件为奥林巴斯原厂配件,仪景通公司对售出的维修配件不提供保修服务,也不提供退、换货服务,敬请您谨慎购买。\n';
                Messages01 = '-仪景通光学科技(上海)有限公司北京分公司售出的维修配件为奥林巴斯原厂配件,仪景通公司对售出的维修配件不提供保修服务,也不提供退、换货服务,敬请您谨慎购买。';
            }else {
                QuotesPage.CUSTOMER_MESSAGE__c += '-奥林巴斯服务部售出的维修配件确保为质量符合奥林巴斯参数指标的新品,奥林巴斯对售出的维修配件不提供保修服务,同时也不提供退、换货服务。敬请您谨慎购买。\n';
                Messages01 = '-奥林巴斯服务部售出的维修配件确保为质量符合奥林巴斯参数指标的新品,奥林巴斯对售出的维修配件不提供保修服务,同时也不提供退、换货服务。敬请您谨慎购买。';
            }
            QuotesPage.CUSTOMER_MESSAGE__c += '-奥林巴斯服务部售出的维修配件确保为质量符合奥林巴斯参数指标的新品,奥林巴斯对售出的维修配件不提供保修服务,同时也不提供退、换货服务。敬请您谨慎购买。\n';
            Messages01 = '-奥林巴斯服务部售出的维修配件确保为质量符合奥林巴斯参数指标的新品,奥林巴斯对售出的维修配件不提供保修服务,同时也不提供退、换货服务。敬请您谨慎购买。';
            QuotesPage.CUSTOMER_MESSAGE__c += '-用户在此确认此次报价,决定购买:\n';
            Messages02 = '-用户在此确认此次报价,决定购买:';
            QuotesPage.CUSTOMER_MESSAGE__c += '客户签字或盖章:\n';
@@ -401,7 +404,6 @@
        if (String.isNotBlank(swoId)) {
            QuotesPage.SWO__c = swoId;
            //日期2121年11月15号之后的,用新的免责申明。
            aftORbef = true;
        }
        if (!'Cancel'.equals(QuotesPage.STATUS__c)) {
force-app/main/default/classes/NewLoanerApplicationController.cls
@@ -5,12 +5,27 @@
    public String contactID {get; private set;}
    public loaner_application__c la{get; private set;}
    // Update 20220318 By Yang Kaiyu Start
    public loaner_user__c lu {get; private set;}
    public Contact con {get; private set;}
    // Update 20220318 By Yang Kaiyu End
    public String typeName {get; private set;}
    public String userType {get; private set;}
    public String baseUrl { get; set; }
    public String rtUrl { get; set; }
    // Update 20220318 By Yang Kaiyu Start
    public String staticResource {get; set;}
    public String staticResourceContact {get; set;}
    public String staticResourceLoanerUser {get; set;}
    public String laid {get; set;}
    // Update 20220318 By Yang Kaiyu End
    public NewLoanerApplicationController() {
        baseUrl = URL.getSalesforceBaseUrl().toExternalForm();
@@ -30,6 +45,11 @@
        userType = UserInfo.getUserType();
        accountID = System.currentPageReference().getParameters().get('accid');
        contactID = System.currentPageReference().getParameters().get('conId');
        // Update 20220318 By Yang Kaiyu End
        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('loaner_application__c'));
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('Contact'));
        staticResourceLoanerUser = JSON.serialize(PIHelper.getPIIntegrationInfo('loaner_user__c'));
        // Update 20220318 By Yang Kaiyu End
        Account acc = [select id,ProductSegment__c from Account where id = :accountID];
        typeName = acc.ProductSegment__c;
@@ -37,12 +57,19 @@
                  .get(typeName).getRecordTypeId();
        
        la = new loaner_application__c();
        // Update 20220318 By Yang Kaiyu End
        lu = new loaner_user__c();
        con = new Contact();
        // Update 20220318 By Yang Kaiyu End
        la.RecordTypeId= recordTypeId;
        if(typeName == 'BS' && userType != 'Standard'){
            la.RecordTypeId = System.label.bs_D_ID;
        }
        System.debug(la.RecordTypeId);
        //ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error,accountID));
        // Update 20220318 By Yang Kaiyu End
        con = [select id,AWS_Data_Id__c,Phone,Phone_Encrypted__c,Name,LastName_Encrypted__c,Address1__c from Contact where id = :contactID];
        // Update 20220318 By Yang Kaiyu End
        return null;
    }
@@ -61,21 +88,27 @@
         Savepoint sp = Database.setSavepoint();
        try {
            insert la;
            loaner_user__c lu = new loaner_user__c();
            // loaner_user__c lu = new loaner_user__c();   // Update 20220412 By Chen Yanan
            lu.loaner_application__c = la.id;
            lu.Customer__c = accountID;
             if(contactID != null){
                 lu.Contact__c = contactID;
                 Contact contact = [select id,Phone,Name,Address1__c from Contact where id = :contactID];
                 lu.ContactNumber__c = contact.Phone;
            // Update 20220318 By Yang Kaiyu Start
            // System.debug('lu------------'+lu);
             // if(contactID != null){
             //     lu.Contact__c = contactID;
             //     Contact contact = [select id,AWS_Data_Id__c,Phone,Phone_Encrypted__c,Name,LastName_Encrypted__c,Address1__c from Contact where id = :contactID];
             //     lu.ContactNumber__c = contact.Phone;
                 
             }
             // }
            // Update 20220318 By Yang Kaiyu End
             
            insert lu;
            String url = baseUrl + '\\' + la.Id;
            return new Pagereference(url);
            // Update 20220318 By Yang Kaiyu Start
            laid = la.id;
            // String url = baseUrl + '\\' + la.Id;
            // return new Pagereference(url);
            return null;
            // Update 20220318 By Yang Kaiyu End
        } catch (Exception e) {
            Database.rollback(sp);
            ApexPages.addmessage(new ApexPages.message(ApexPages.severity.Error, e.getMessage()));
force-app/main/default/classes/NewLoanerUserController.cls
@@ -7,7 +7,27 @@
    public List<loaner_user__c> dataLines {get; private set;}
    //订单Id
    public String laId {get; private set;}
    //
    // Update 20220317 By Yang Kaiyu Start
    public String staticResource {get; set;}
    public String staticResourceContact {get; set;}
    //PI contact
    public List<ContactClass> conList {get;set;}
    public String contactId {get;set;}
    public string conListJson {get{
        if(conList==null)return null;
        return JSON.serialize(conList);
    }}
    public String dataLinesJson{get{
        if(dataLines==null)return null;
        return JSON.serialize(dataLines);
    }}
    class ContactClass{
        public String contactIdValue{set;get;}
        public String contactNameValue{set;get;}
        public String contactPhoneValue{set;get;}
    }
    // Update 20220317 By Yang Kaiyu End
    /*public NewLoanerUserController() {
         laId = System.currentPageReference().getParameters().get('headId');
         //ApexPages.currentPage().getParameters().get('headId');
@@ -21,7 +41,12 @@
        }else{
            loaner_user__c lu = [select id,loaner_application__c from loaner_user__c where id = :luId];
            laId = lu.loaner_application__c; 
        }
        }
        // Update 20220317 By Yang Kaiyu Start
        staticResource = JSON.serialize(PIHelper.getPIIntegrationInfo('loaner_user__c'));
        staticResourceContact = JSON.serialize(PIHelper.getPIIntegrationInfo('contact'));
        conList = new List<ContactClass>();
        // Update 20220317 By Yang Kaiyu End
    }
    
@@ -37,9 +62,21 @@
            baseUrl += '/production';
        }
        dataLines = new List<loaner_user__c>();
        luList = [select id,Contact__c,ContactNumber__c,FromThePeriod__c,EndThePeriod__c,Remarks__c,Customer__c,Follow_UP_Opp__c from loaner_user__c where  loaner_application__c =:laId];
        // Update 20220317 By Yang Kaiyu Start
        luList = [select id,Contact__r.AWS_Data_Id__c,Contact__c,Contact__r.LastName,Contact__r.Phone,Contact__r.LastName_Encrypted__c,Contact__r.Phone_Encrypted__c,ContactNumber__c,
                        FromThePeriod__c,EndThePeriod__c,Remarks__c,Customer__c,Follow_UP_Opp__c
                    from loaner_user__c
                    where  loaner_application__c =:laId];
        // Update 20220317 By Yang Kaiyu End
        if(luList.size() >0){
            for(loaner_user__c lu : luList){
                // Update 20220317 By Yang Kaiyu Start
                ContactClass con = new ContactClass();
                con.contactIdValue   = lu.Contact__r.AWS_Data_Id__c;
                con.contactNameValue = lu.Contact__r.LastName_Encrypted__c;
                con.contactPhoneValue= lu.Contact__r.Phone_Encrypted__c;
                conList.add(con);
                // Update 20220317 By Yang Kaiyu End
                dataLines.add(lu);
            }
        }
@@ -55,6 +92,8 @@
    public PageReference updateUser() {
        System.debug('进入updateUser');
        List<loaner_user__c> updateList = new List<loaner_user__c>();
        loaner_application__c la =[select id,RecordType.DeveloperName from loaner_application__c where id=:laId];
        List<String> contactIdList = new List<String>();
@@ -62,6 +101,7 @@
        String firstLuId = '';
        String accountName = '';
        List<String> idList = new List<String>();
        System.debug('dataLines = ' + dataLines);
        for(loaner_user__c luc : dataLines){
            if(!(String.isBlank(luc.Contact__c) || luc.Customer__c == null)){
                loaner_user__c lu = new loaner_user__c();
force-app/main/default/classes/SBG027TriggerHandleTest.cls
@@ -106,7 +106,7 @@
        opp.Dealer__c = buyer.Id;
        opp.RecordTypeId = rectOpp[0].Id;
        opp.OwnerId = UserInfo.getUserId();
        opp.StageName = 'Phase3';
        opp.StageName = 'Phase3';//修改为Prospect Created 原来是Phase3
        opp.CurrencyIsoCode = 'CNY';
        opp.ProductSegment__c = 'IE';
        opp.CloseDate = Date.today();
force-app/main/default/pages/ContactFileUploadPage.page
New file
@@ -0,0 +1,195 @@
<!-- 该页面用于Lead对象上传PDF,未来如果要添加其他对象的上传PDF功能,复制该页面,将**standardController**修改为其他对象API名称即可 -->
<apex:page standardController="Contract" 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:relatedList  list="CombinedAttachments" >
    </apex:relatedList>
    <script>
        const element = document.getElementsByName('attachFile')[0];
        element.remove();
    </script>
</apex:page>
force-app/main/default/pages/ContactFileUploadPage.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>ContactFileUploadPage</label>
</ApexPage>
force-app/main/default/pages/LoanerUploadFilePage.page
New file
@@ -0,0 +1,198 @@
<!-- 该页面用于Lead对象上传PDF,未来如果要添加其他对象的上传PDF功能,复制该页面,将**standardController**修改为其他对象API名称即可 -->
<apex:page standardController="loaner_application__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="附件" 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:relatedList  list="CombinedAttachments" id="Notes">
        <apex:facet name="NoteHeader" ></apex:facet>
    </apex:relatedList>
    <script>
        const element = document.getElementsByName('attachFile')[0];
        element.remove();
        document.getElementById('page:Notes_title').innerText = '备注';
    </script>
</apex:page>
force-app/main/default/pages/LoanerUploadFilePage.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>LoanerUploadFilePage</label>
</ApexPage>
force-app/main/default/pages/NEWCreateSWOQuote.page
@@ -7,8 +7,88 @@
<apex:includeScript value="{!URLFOR($Resource.SWOJS)}"/>
<apex:includeScript value="{!URLFOR($Resource.connection20)}"/>
<apex:includeScript value="{!URLFOR($Resource.apex20)}"/>
<apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
<script type="text/javascript">
    // 20220311 PI改造 by Bright start
    AWSService.sfSessionId = '{!GETSESSIONID()}';
    var staticResource = JSON.parse('{!staticResource}');
    var contactstaticResource = JSON.parse('{!contactstaticResource}');
    var aws_data = {};
    function Decrypt(r,dataIds,callback){
        if (!(dataIds && dataIds.length)) {
            if(callback)callback();
            return;
        }
        let Foo = function(){
            for (const id of dataIds) {
                if (aws_data.hasOwnProperty(id)) {
                    let d = aws_data[id];
                    let $e =j$("[aws-id='"+d.dataId+ "']");
                    $e.each((i,e)=>{
                        j$(e).html(d[j$(e).attr("aws-api")]);
                    })
                }
            }
            if(callback)callback();
        }
        let ids = [];
        for (const id of dataIds) {
            if (!aws_data.hasOwnProperty(id)) {
                ids.push(id);
            }
        }
        if (ids.length > 0) {
            AWSService.search(r.searchUrl,JSON.stringify({
                "dataIds":ids
            }),function(data){
                if(data.object && data.object.length > 0){
                    for(let d of data.object){
                        if(d.dataId){
                            aws_data[d.dataId] = d;
                        }
                    }
                    Foo();
                }else{
                    if(callback)callback();
                }
            },r.token);
        }else{
            Foo();
        }
    }
    function DecryptAll(callback){
        let dataIds1 = [];
        j$('[aws-id][aws-obj="Contact"]').each((i,e)=>{
            let v = j$(e).attr('aws-id');
            if (v) {
                dataIds1.push(v);
            }
        });
        Decrypt(contactstaticResource,dataIds1,callback);
        let dataIds2 = [];
        j$('[aws-id][aws-obj="Quotes__c"]').each((i,e)=>{
            let v = j$(e).attr('aws-id');
            if (v) {
                dataIds2.push(v);
            }
        });
        Decrypt(staticResource,dataIds2,callback);
    }
    j$(function(){
        DecryptAll();
    })
    // 20220311 PI改造 by Bright end
</script>
<style type="text/css"> 
        .Page{
@@ -133,7 +213,9 @@
                        <tr>
                            <td colspan="2" align="left" ><apex:inputField id="CURRENCY" value="{!QuotesPage.CURRENCY__c}" style="width: 56%"/></td>
                            <td colspan="2" align="left" ><apex:outputField value="{!QuotesPage.CONTACT_NAME__c}" style="width: 63%"/></td>
                            <td colspan="2" align="left" >
                                <a href="/{!QuotesPage.CONTACT_NAME__c}" aws-obj="Contact" aws-api="lastName" aws-id="{!QuotesPage.CONTACT_NAME__r.AWS_Data_Id__c}">{!QuotesPage.CONTACT_NAME__r.Name}</a>
                            </td>
                            <td colspan="2"/>
                            <td colspan="2" class="title1">Summary</td>
                            <td/>
@@ -154,7 +236,7 @@
                            <td colspan="2" align="left" ><apex:outputField id="COMPANY" value="{!QuotesPage.COMPANY__c}"/>
                            <!-- <apex:outputLink value="/{!QuotesPage.COMPANYId__c}" target="LINK_{!QuotesPage.COMPANYId__c}" ><c:PDFWbr targetStr="{!QuotesPage.COMPANYName__c}"/></apex:outputLink> -->
                            </td>
                            <td align="left" ><apex:outputField id="CONTACT_PHONE" value="{!QuotesPage.CONTACT_PHONE__c}"/></td>
                            <td align="left" ><apex:outputField html-aws-obj="Quotes__c" html-aws-api="contactPhone" html-aws-id="{!QuotesPage.AWS_Data_Id__c}" id="CONTACT_PHONE" value="{!QuotesPage.CONTACT_PHONE__c}"/></td>
                            <td colspan="3"/>
                            <td class="title2">{!$ObjectType.Quotes__c.fields.DISCOUNT__c.label}</td>
                            <td class="title2" align="left" ><apex:outputField value="{!QuotesPage.DISCOUNT__c}" style="width: 62%"/></td>
@@ -295,7 +377,7 @@
                                <apex:inputText id="DisplayPROBABILITY" value="{!QuotesPage.PROBABILITY__c}" style="display: none;"/>
                            </td>
                            <td/>
                            <td align="left" ><apex:inputField id="PRODUCT_SEGMENT" value="{!QuotesPage.PRODUCT_SEGMENT__c}"  onchange="QuotesTypeChangeFunction();" style="width: 95%"/></td>
                            <td align="left" ><apex:inputField id="PRODUCT_SEGMENT" value="{!QuotesPage.PRODUCT_SEGMENT__c}" style="width: 95%"/></td>
                        </tr>
                        <tr>
                            <td align="left" >{!$ObjectType.Quotes__c.fields.LOCATION__c.label}<span class="textRed">*</span></td>
@@ -445,8 +527,8 @@
                            <td align="left" >{!$ObjectType.Quotes__c.fields.SHIP_TO__c.label}</td>
                        </tr>
                        <tr>
                            <td colspan="2" align="left" ><apex:inputField id="BILL_TO" value="{!QuotesPage.BILL_TO__c }" style="width: 90%;height: 80PX"/></td>
                            <td colspan="2" align="left" ><apex:inputField id="SHIP_TO" value="{!QuotesPage.SHIP_TO__c}" style="width: 90%;height: 80PX"/></td>
                            <td colspan="2" align="left" ><apex:inputField html-aws-obj="Quotes__c" html-aws-api="billTo" html-aws-id="{!QuotesPage.AWS_Data_Id__c}" id="BILL_TO" value="{!QuotesPage.BILL_TO__c }" style="width: 90%;height: 80PX"/></td>
                            <td colspan="2" align="left" ><apex:inputField html-aws-obj="Quotes__c" html-aws-api="shipTo" html-aws-id="{!QuotesPage.AWS_Data_Id__c}" id="SHIP_TO" value="{!QuotesPage.SHIP_TO__c}" style="width: 90%;height: 80PX"/></td>
                        </tr>
                        <tr>
                             <td colspan="9"> <hr/></td>
@@ -566,17 +648,19 @@
                        </tr>
                        
                                <tr>
                                    <td colspan="9">
                                    <apex:outputText id="message01" value="{!Messages01}" style="resize:vertical;width: 100%"/>
                                    </td>
                                    <apex:outputPanel layout="none" rendered="{!IF(aftORbef == false && aftORbef1 == false, true, false)}">
                                        <td colspan="9">
                                        <apex:outputText id="message01" value="{!Messages01}" style="resize:vertical;width: 100%"/>
                                        </td>
                                    </apex:outputPanel>
                                </tr>
                                <!-- <tr>
                                <tr>
                                    <apex:outputPanel layout="none" rendered="{!IF(aftORbef == true || aftORbef1 == true, true, false)}">
                                        <td colspan="9">
                                        <apex:outputText value="-维修质保只涵盖于本次维修的配件,维修质保期为仪器发货后三个月加八天。" style="resize:vertical;width: 100%"/>
                                        </td>
                                    </apex:outputPanel> 
                                </tr> -->
                                </tr>
                                <tr>
                                    <td colspan="9">
                                     <apex:outputText id="message02" value="{!Messages02}" style="resize:vertical;width: 100%"/>
force-app/main/default/pages/NEWCreateSWOQuoteReadOnly.page
@@ -6,9 +6,89 @@
<apex:includeScript value="{!URLFOR($Resource.NewQuoteEntryJS)}"/>
<apex:includeScript value="{!URLFOR($Resource.connection20)}"/>
<apex:includeScript value="{!URLFOR($Resource.apex20)}"/>
<apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
<script type="text/javascript">
        // 20220311 PI改造 by Bright start
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResource = JSON.parse('{!staticResource}');
        var contactstaticResource = JSON.parse('{!contactstaticResource}');
        var aws_data = {};
        function Decrypt(r,dataIds,callback){
            if (!(dataIds && dataIds.length)) {
                if(callback)callback();
                return;
            }
            let Foo = function(){
                for (const id of dataIds) {
                    if (aws_data.hasOwnProperty(id)) {
                        let d = aws_data[id];
                        let $e =j$("[aws-id='"+d.dataId+ "']");
                        $e.each((i,e)=>{
                            j$(e).html(d[j$(e).attr("aws-api")]);
                        })
                    }
                }
                if(callback)callback();
            }
            let ids = [];
            for (const id of dataIds) {
                if (!aws_data.hasOwnProperty(id)) {
                    ids.push(id);
                }
            }
            if (ids.length > 0) {
                AWSService.search(r.searchUrl,JSON.stringify({
                    "dataIds":ids
                }),function(data){
                    if(data.object && data.object.length > 0){
                        for(let d of data.object){
                            if(d.dataId){
                                aws_data[d.dataId] = d;
                            }
                        }
                        Foo();
                    }else{
                        if(callback)callback();
                    }
                },r.token);
            }else{
                Foo();
            }
        }
        function DecryptAll(callback){
            let dataIds1 = [];
            j$('[aws-id][aws-obj="Contact"]').each((i,e)=>{
                let v = j$(e).attr('aws-id');
                if (v) {
                    dataIds1.push(v);
                }
            });
            Decrypt(contactstaticResource,dataIds1,callback);
            let dataIds2 = [];
            j$('[aws-id][aws-obj="Quotes__c"]').each((i,e)=>{
                let v = j$(e).attr('aws-id');
                if (v) {
                    dataIds2.push(v);
                }
            });
            Decrypt(staticResource,dataIds2,callback);
        }
        j$(function(){
            DecryptAll();
        })
        // 20220311 PI改造 by Bright end
        
        function openPDF(){
            
@@ -137,7 +217,9 @@
                        <tr>
                            <td colspan="2" align="left" ><apex:outputField id="CURRENCY" value="{!QuotesPage.CURRENCY__c}" style="width: 56%"/></td>
                            <td colspan="2" align="left" ><apex:outputField value="{!QuotesPage.CONTACT_NAME__c}" style="width: 63%"/></td>
                            <td colspan="2" align="left" >
                                <a href="/{!QuotesPage.CONTACT_NAME__c}" aws-obj="Contact" aws-api="lastName" aws-id="{!QuotesPage.CONTACT_NAME__r.AWS_Data_Id__c}">{!QuotesPage.CONTACT_NAME__r.Name}</a>
                            </td>
                            <td colspan="2"/>
                            <td colspan="2" class="title1">Summary</td>
                            <td/>
@@ -157,7 +239,7 @@
                        <tr>
                            <td colspan="2" align="left" ><apex:outputField id="COMPANY" value="{!QuotesPage.COMPANY__c}"/>
                            </td>
                            <td align="left" ><apex:outputField id="CONTACT_PHONE" value="{!QuotesPage.CONTACT_PHONE__c}"/></td>
                            <td align="left" ><apex:outputField html-aws-obj="Quotes__c" html-aws-api="contactPhone" html-aws-id="{!QuotesPage.AWS_Data_Id__c}" id="CONTACT_PHONE" value="{!QuotesPage.CONTACT_PHONE__c}"/></td>
                            <td colspan="3"/>
                            <td class="title2">{!$ObjectType.Quotes__c.fields.DISCOUNT__c.label}</td>
                            <td class="title2" align="left" ><apex:outputField value="{!QuotesPage.DISCOUNT__c}" style="width: 62%"/></td>
@@ -460,8 +542,8 @@
                            <td class="hand" align="left" >{!$ObjectType.Quotes__c.fields.SHIP_TO__c.label}</td>
                        </tr>
                        <tr>
                            <td colspan="2" align="left" ><apex:outputField id="BILL_TO" value="{!QuotesPage.BILL_TO__c }" style="width: 90%;height: 80PX"/></td>
                            <td colspan="2" align="left" ><apex:outputField id="SHIP_TO" value="{!QuotesPage.SHIP_TO__c}" style="width: 90%;height: 80PX"/></td>
                            <td colspan="2" align="left" ><apex:outputField html-aws-obj="Quotes__c" html-aws-api="billTo" html-aws-id="{!QuotesPage.AWS_Data_Id__c}" id="BILL_TO" value="{!QuotesPage.BILL_TO__c }" style="width: 90%;height: 80PX"/></td>
                            <td colspan="2" align="left" ><apex:outputField html-aws-obj="Quotes__c" html-aws-api="shipTo" html-aws-id="{!QuotesPage.AWS_Data_Id__c}" id="SHIP_TO" value="{!QuotesPage.SHIP_TO__c}" style="width: 90%;height: 80PX"/></td>
                        </tr>
                        <tr>
                             <td colspan="9"> <hr/></td>
force-app/main/default/pages/NewLoanerApplication.page
@@ -2,26 +2,212 @@
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <!-- Update 20220318 By Yang Kaiyu Start -->
    <apex:includeScript value="{!URLFOR($Resource.CommonUtilJs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:includeScript value="/soap/ajax/40.0/connection.js"/>
    <!-- Update 20220318 By Yang Kaiyu End -->
    <script>
    function saveJs() {
        blockme();
        saveBtn();
    }
    function cancelJs() {
        var baseUrl = '{!baseUrl}';
        var rtUrl = '{!contactID}';
        if (rtUrl == 'null' || rtUrl == '') {
            rtUrl = '{!accountID}';
        // Update 20220318 By Yang Kaiyu Start
        aws_result = '';
        lu_aws_result = '';
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResource = JSON.parse('{!staticResource}');
        var staticResourceContact = JSON.parse('{!staticResourceContact}');
        var staticResourceLoanerUser = JSON.parse('{!staticResourceLoanerUser}');
        function searchPI(){
            console.log('---searchPI---');
            var conAwsDataid ='';
            conAwsDataid = document.getElementById("page:mainfrom:idSearchSetProduct:con_AWS_Data_Id__c").value;
            if(conAwsDataid){
                blockme();
                console.log('---AWSService---');
                AWSService.query(staticResourceContact.queryUrl,conAwsDataid,function(data){
                    unblockUI();
                    if(data.object){
                        console.log('----------------data-----------------');
                        console.log(data);
                        console.log('----------------data-----------------');
                        document.getElementById("page:mainfrom:idSearchSetProduct:Contact__c").value = '{!contactID}';
                        document.getElementById("page:mainfrom:idSearchSetProduct:ContactNumber__c").value = data.object.phone;
                        if(document.getElementById("page:mainfrom:idSearchSetProduct:ContactNumber__c").value){
                            AWSService.post(staticResourceLoanerUser.newUrl, GetLUObj(), function(result){
                                if(result && result.object){
                                    lu_aws_result = result;
                                    console.log('----------------result-----------------');
                                    console.log(result);
                                    console.log('----------------result-----------------');
                                    document.getElementById("page:mainfrom:idSearchSetProduct:lu_AWS_Data_Id__c").value = result.object.dataId;
                                    document.getElementById("page:mainfrom:idSearchSetProduct:ContactNumber__c").value = result.object.phone;
                                    document.getElementById("page:mainfrom:idSearchSetProduct:ContactNumber_Encrypted__c").value = result.object.phoneEncrypted;
                                }
                            }, staticResourceLoanerUser.token);
                        }
                    }
                },staticResourceContact.token);
            }
        }
        window.location.href = baseUrl + "/" + rtUrl;
    }
        function GetLUObj(){
            return JSON.stringify([{
                contactNumber : document.getElementById("page:mainfrom:idSearchSetProduct:ContactNumber__c").value,
                dataId : document.getElementById("page:mainfrom:idSearchSetProduct:lu_AWS_Data_Id__c").value,
            }]);
        }
        function ProcessPI(sobjJson, payloadForNewPI,callback) {
            console.log('---insert---');
            AWSService.post(staticResource.newUrl, payloadForNewPI, function(result){
                aws_result = result
                SetEditObj();
                if(callback){
                    callback();
                }
            }, staticResource.token);
        }
        function SetEditObj(){
            let obj = GetAWSResultObj();
            if(obj){
                document.getElementById("page:mainfrom:idSearchSetProduct:AWS_Data_Id__c").value                                = obj.dataId;
                document.getElementById("page:mainfrom:idSearchSetProduct:ReceiveInfo:pc:Post_Code__c").value                   = obj.postCode;
                document.getElementById("page:mainfrom:idSearchSetProduct:ReceiveInfo:lrsp:Loaner_receive_staff_phone__c").value= obj.loanerReceiveStaffPhone;
                document.getElementById("page:mainfrom:idSearchSetProduct:ReceiveInfo:lrs:Loaner_receive_staff__c").value       = obj.loanerReceiveStaff;
                document.getElementById("page:mainfrom:idSearchSetProduct:LoanerApplicationDetailInfo:ls:Loaner_Ser__c").value  = obj.loanerSer;
                document.getElementById("page:mainfrom:idSearchSetProduct:ReceiveInfo:dsa:direct_shippment_address__c").value   = obj.directShippmentAddress;
                document.getElementById("page:mainfrom:idSearchSetProduct:direct_shippment_address_Encrypted__c").value         = obj.directShippmentAddressEncrypt;
                document.getElementById("page:mainfrom:idSearchSetProduct:Pos_Code_Encrypted__c").value                         = obj.postCodeEncrypt;
                document.getElementById("page:mainfrom:idSearchSetProduct:Loaner_receive_staff_phone_Encrypted__c").value       = obj.loanerReceiveStaffPhoneEncrypt;
                document.getElementById("page:mainfrom:idSearchSetProduct:Loaner_receive_staff_Encrypted__c").value             = obj.loanerReceiveStaffEncrypt;
                document.getElementById("page:mainfrom:idSearchSetProduct:Loaner_Ser_Encrypted__c").value                       = obj.loanerSerEncrypt;
            }
        }
        function GetAWSResultObj(){
            if(aws_result && aws_result.object && aws_result.object.length > 0){
                return aws_result.object[0];
            }
            return null;
        }
        function GetObj(){
            return JSON.stringify([{
                dataId : document.getElementById("page:mainfrom:idSearchSetProduct:AWS_Data_Id__c").value,
                postCode : document.getElementById("page:mainfrom:idSearchSetProduct:ReceiveInfo:pc:Post_Code__c").value,
                loanerReceiveStaffPhone : document.getElementById("page:mainfrom:idSearchSetProduct:ReceiveInfo:lrsp:Loaner_receive_staff_phone__c").value,
                loanerReceiveStaff : document.getElementById("page:mainfrom:idSearchSetProduct:ReceiveInfo:lrs:Loaner_receive_staff__c").value,
                loanerSer : document.getElementById("page:mainfrom:idSearchSetProduct:LoanerApplicationDetailInfo:ls:Loaner_Ser__c").value,
                directShippmentAddress : document.getElementById("page:mainfrom:idSearchSetProduct:ReceiveInfo:dsa:direct_shippment_address__c").value,
            }]);
        }
        var bt1 = false;
        var bt2 = false;
        var laid = '';
        function Redirect(){
            if(bt1 && bt2){
                window.location.href = '/'+laid;
            }
        }
        //aws 确认
        function Transla(){
            let e = HasError();
            if(!e){
                AWSService.post(staticResourceLoanerUser.transactionUrl, JSON.stringify({
                    "txId":lu_aws_result.txId,
                    "isSuccess":e ? 0 : 1
                }), function(result){
                    console.log('---result---');
                    console.log(result);
                    console.log('finish');
                    bt1=true;
                    Redirect();
                    //window.location.reload();
                }, staticResourceLoanerUser.token);
            }
        }
        function Trans(){
            let b = HasError();
            console.log('---HasError---');
            console.log(b);
            console.log('---aws_result---');
            console.log(aws_result);
            if(b){
                //清空pi
                document.getElementById('page:mainfrom:idSearchSetProduct:ReceiveInfo:pc:Post_Code__c').value=''
                document.getElementById('page:mainfrom:idSearchSetProduct:ReceiveInfo:lrsp:Loaner_receive_staff_phone__c').value=''
                document.getElementById('page:mainfrom:idSearchSetProduct:ReceiveInfo:lrs:Loaner_receive_staff__c').value=''
                document.getElementById('page:mainfrom:idSearchSetProduct:LoanerApplicationDetailInfo:ls:Loaner_Ser__c').value=''
                document.getElementById('page:mainfrom:idSearchSetProduct:ReceiveInfo:dsa:direct_shippment_address__c').value=''
            }
            AWSService.post(staticResource.transactionUrl, JSON.stringify({
                    "txId":aws_result.txId,
                    "isSuccess":b ? 0 : 1
                }), function(result){
                    console.log('---result---');
                    console.log(result);
                    console.log('finish');
                    bt2=true;
                    Redirect();
                    //window.location.reload();
                }, staticResource.token);
        }
        function HasError(){
            let e = document.getElementById("page:mainfrom:message");
            console.log(e);
            if (!e) {
                return false;
            }
            if(j$(e).find(".editListError").length > 0){
                return true;
            }
            let divs = j$(e).find("div.message");
            for (let i = 0; i < divs.length; i++) {
                for (let j = 0; j < divs[i].classList.length; j++) {
                    for(let cls in divs[i].classList){
                        if (cls.indexOf('error')>-1) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        // Update 20220318 By Yang Kaiyu End
        function saveJs() {
            blockme();
            // Update 20220318 By Yang Kaiyu Start
            searchPI();
            ProcessPI({},GetObj(),function(){
                saveBtn();
            });
            // Update 20220318 By Yang Kaiyu End
        }
        function cancelJs() {
            var baseUrl = '{!baseUrl}';
            var rtUrl = '{!contactID}';
            if (rtUrl == 'null' || rtUrl == '') {
                rtUrl = '{!accountID}';
            }
            window.location.href = baseUrl + "/" + rtUrl;
        }
    </script>
    <apex:form id="mainfrom">
        <apex:actionFunction action="{!saveBtn}" name="saveBtn" reRender="mainForm,message" oncomplete="unblockUI();"/>
        <!-- Update 20220318 By Yang Kaiyu Start -->
        <script>
            laid = '{!laid}';
        </script>
        <!-- Update 20220318 By Yang Kaiyu End -->
        <apex:actionFunction action="{!saveBtn}" name="saveBtn" reRender="mainfrom,message" oncomplete="unblockUI();Transla();Trans();"/>
        <apex:actionFunction action="{!cancelBtn}" name="cancelBtn" reRender="mainForm,message" oncomplete="unblockUI();"/>
        <apex:outputPanel id="message">
@@ -35,7 +221,9 @@
            </apex:pageBlockButtons>
           
            <apex:outputPanel layout="none" >
                <apex:pageBlockSection title="样机借出申请详细信息" columns="2">
                <!-- Update 20220318 By Yang Kaiyu Start -->
                <apex:pageBlockSection id="LoanerApplicationDetailInfo" title="样机借出申请详细信息" columns="2">
                <!-- Update 20220318 By Yang Kaiyu End -->
                    <apex:pageBlockSectionItem >
                        <apex:outputLabel value="样机借出申请名称" for="la_Name"/>
@@ -45,11 +233,15 @@
                        <apex:outputLabel value="样机分类" for="la_Type"/>
                        <apex:inputField value="{!la.Equipment_Type__c}" id="la_Type" required="true"/>
                    </apex:pageBlockSectionItem>
                    <apex:pageBlockSectionItem >
                    <!-- Update 20220318 By Yang Kaiyu Start -->
                    <apex:pageBlockSectionItem id="ls" >
                    <!-- Update 20220318 By Yang Kaiyu End -->
                        <apex:outputLabel value="借用担当" for="Loaner_Ser__c"/>
                        <apex:inputField value="{!la.Loaner_Ser__c}" id="Loaner_Ser__c" required="true"/>
                        <!-- Update 20220318 By Yang Kaiyu Start -->
                        <apex:inputField value="{!la.Loaner_Ser__c}" id="Loaner_Ser__c" required="true"/><!--pi-->
                        <!-- Update 20220318 By Yang Kaiyu End -->
                    </apex:pageBlockSectionItem>
                        <apex:pageBlockSectionItem rendered="{!IF(userType == 'Standard', false , true)}">
                            <apex:outputLabel value="审批人" for="Approver__c"/>
                            <apex:inputField value="{!la.Approver__c}" id="Approver__c" required="true"/>
@@ -317,35 +509,70 @@
                    </apex:pageBlockSectionItem>
                </apex:pageBlockSection>
                <apex:pageBlockSection title="收件人信息" columns="2">
                    <apex:pageBlockSectionItem >
                <!-- Update 20220318 By Yang Kaiyu Start -->
                <apex:pageBlockSection id="ReceiveInfo" title="收件人信息" columns="2">
                    <apex:pageBlockSectionItem id="lrs" >
                        <!-- Update 20220318 By Yang Kaiyu End -->
                        <apex:outputLabel value="收件人姓名" for="Loaner_receive_staff__c"/>
                        <apex:inputField value="{!la.Loaner_receive_staff__c}" id="Loaner_receive_staff__c"/>
                        <!-- Update 20220318 By Yang Kaiyu Start -->
                        <apex:inputField value="{!la.Loaner_receive_staff__c}" id="Loaner_receive_staff__c"/><!--pi-->
                        <!-- Update 20220318 By Yang Kaiyu End -->
                    </apex:pageBlockSectionItem>
                    <apex:pageBlockSectionItem >
                         <apex:outputLabel value="自提时间" for="pickup_time__c"/>
                        <apex:inputField value="{!la.pickup_time__c}" id="pickup_time__c"/>
                    </apex:pageBlockSectionItem>  
                    <apex:pageBlockSectionItem >
                    <!-- Update 20220318 By Yang Kaiyu Start -->
                    <apex:pageBlockSectionItem id="dsa" >
                    <!-- Update 20220318 By Yang Kaiyu End -->
                        <apex:outputLabel value="收件人详细地址" for="direct_shippment_address__c"/>
                        <apex:inputField value="{!la.direct_shippment_address__c}" id="direct_shippment_address__c"/>
                        <!-- Update 20220318 By Yang Kaiyu Start -->
                        <apex:inputField value="{!la.direct_shippment_address__c}" id="direct_shippment_address__c"/><!--pi-->
                        <!-- Update 20220318 By Yang Kaiyu End -->
                    </apex:pageBlockSectionItem>
                    <apex:pageBlockSectionItem >
                        &nbsp;
                    </apex:pageBlockSectionItem>
                    <apex:pageBlockSectionItem >
                    <!-- Update 20220318 By Yang Kaiyu Start -->
                    <apex:pageBlockSectionItem id="lrsp" >
                    <!-- Update 20220318 By Yang Kaiyu End -->
                        <apex:outputLabel value="收件人电话" for="Loaner_receive_staff_phone__c"/>
                        <apex:inputField value="{!la.Loaner_receive_staff_phone__c}" id="Loaner_receive_staff_phone__c"/>
                        <!-- Update 20220318 By Yang Kaiyu Start -->
                        <apex:inputField value="{!la.Loaner_receive_staff_phone__c}" id="Loaner_receive_staff_phone__c"/><!--pi-->
                        <!-- Update 20220318 By Yang Kaiyu Emd -->
                    </apex:pageBlockSectionItem>
                    <apex:pageBlockSectionItem >
                        &nbsp;
                    </apex:pageBlockSectionItem>
                    <apex:pageBlockSectionItem >
                    <!-- Update 20220318 By Yang Kaiyu Start -->
                    <apex:pageBlockSectionItem id="pc" >
                    <!-- Update 20220318 By Yang Kaiyu End -->
                        <apex:outputLabel value="邮编" for="Post_Code__c"/>
                        <apex:inputField value="{!la.Post_Code__c}" id="Post_Code__c"/>
                    </apex:pageBlockSectionItem>
                        <!-- Update 20220318 By Yang Kaiyu Start -->
                        <apex:inputField value="{!la.Post_Code__c}" id="Post_Code__c"/><!--pi-->
                        <!-- Update 20220318 By Yang Kaiyu End -->
                    </apex:pageBlockSectionItem>
                </apex:pageBlockSection>
                <!-- Update 20220318 By Yang Kaiyu Start -->
                <apex:inputHidden id="AWS_Data_Id__c" value="{!la.AWS_Data_Id__c}"/>
                <apex:inputHidden id="Loaner_Ser_Encrypted__c"  value="{!la.Loaner_Ser_Encrypted__c}"/>
                <apex:inputHidden id="Pos_Code_Encrypted__c" value="{!la.Pos_Code_Encrypted__c}"/>
                <apex:inputHidden id="direct_shippment_address_Encrypted__c" value="{!la.direct_shippment_address_Encrypted__c}"/>
                <apex:inputHidden id="Loaner_receive_staff_phone_Encrypted__c" value="{!la.Loaner_receive_staff_phone_Encrypted__c}"/>
                <input id="page:mainfrom:idSearchSetProduct:Loaner_receive_staff_Encrypted__c" type="hidden" name="page:mainfrom:idSearchSetProduct:Loaner_receive_staff_Encrypted__c" value="{!la.Loaner_receive_staff_Encrypted__c}"/>
                <apex:inputHidden id="Contact__c" value="{!lu.Contact__c}"/>
                <!-- <apex:inputHidden id="lu_AWS_Data_Id__c" value="{!lu.AWS_Data_Id__c}"/>  -->
                <apex:inputHidden id="ContactNumber__c" value="{!lu.ContactNumber__c}"/>
                <apex:inputHidden id="ContactNumber_Encrypted__c" value="{!lu.ContactNumber_Encrypted__c}"/>
                <!-- <input id="page:mainfrom:idSearchSetProduct:Contact__c" type="hidden" name="page:mainfrom:idSearchSetProduct:Contact__c" value="{!lu.Contact__c}"/> -->
                <input id="page:mainfrom:idSearchSetProduct:lu_AWS_Data_Id__c" type="hidden" name="page:mainfrom:idSearchSetProduct:lu_AWS_Data_Id__c" value="{!lu.AWS_Data_Id__c}"/>
                <!-- <input id="page:mainfrom:idSearchSetProduct:ContactNumber__c" type="hidden" name="page:mainfrom:idSearchSetProduct:ContactNumber__c" value="{!lu.ContactNumber__c}"/> -->
                <!-- <input id="page:mainfrom:idSearchSetProduct:ContactNumber_Encrypted__c" type="hidden" name="page:mainfrom:idSearchSetProduct:ContactNumber_Encrypted__c" value="{!lu.ContactNumber_Encrypted__c}"/> -->
                <apex:inputHidden id="con_AWS_Data_Id__c" value="{!con.AWS_Data_Id__c}"/>
                <apex:inputHidden id="con_id" value="{!con.id}"/>
                <!-- Update 20220318 By Yang Kaiyu End -->
                <apex:pageBlockSection title="备注" >
                    <apex:pageBlockSectionItem >
                        <apex:outputLabel value="备注" for="loaner_Remark__c"/>
@@ -374,7 +601,9 @@
                        <apex:inputField value="{!la.DealerOrder_From__c}" id="DealerOrder_From__c"/>
                    </apex:pageBlockSectionItem>  
                </apex:pageBlockSection>
                <!-- Update 20220318 By Yang Kaiyu Start -->
                <!-- <apex:inputHidden id="Loaner_receive_staff_Encrypted__c" value="{!la.Loaner_receive_staff_Encrypted__c}"/> -->
                <!-- Update 20220318 By Yang Kaiyu End -->
                
force-app/main/default/pages/NewLoanerUser.page
@@ -1,26 +1,180 @@
<apex:page standardController="loaner_user__c" extensions="NewLoanerUserController" showHeader="true" sidebar="false" action="{!init}" title="新建样机借用客户">
<apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
<apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
<apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
<script>
function saveJs() {
    if(confirm('联系人和客户为必填信息,如果为空将不保存此条记录,是否已确认所有需要保存的信息该字段都不为空?')){
        blockme();
        updateUser();
<apex:page standardController="loaner_user__c" extensions="NewLoanerUserController" id="allPage" showHeader="true" sidebar="false" action="{!init}" title="新建样机借用客户">
<!-- <apex:page standardController="loaner_user__c" extensions="NewLoanerUserController" showHeader="true" sidebar="false" action="{!init}" title="新建样机借用客户"> -->
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}"/>
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}"/>
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}"/>
    <!-- Update 20220317 By Yang Kaiyu Start -->
    <apex:includeScript value="{!URLFOR($Resource.CommonUtilJs)}"/>
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:includeScript value="/soap/ajax/40.0/connection.js"/>
    <!-- Update 20220317 By Yang Kaiyu End -->
    <script>
        // Update 20220317 By Yang Kaiyu Start
        AWSService.sfSessionId = '{!GETSESSIONID()}';
        var staticResource = JSON.parse('{!staticResource}');
        var staticResourceContact = JSON.parse('{!staticResourceContact}');
        var aws_data = {};
        let conList = [];
        //替换vlookup
        var closeField = '';
        var newSearchContactWindow = null;
        var contactInfoStr = '';
        var conValue = ''
        //自定义lookup查询
        function searchContact(contactNodeId,field,conValue,conid){
            closeField = conid;
            this.conValue = conValue;
            let accountValue = "";
            if (document.getElementById(field)!=null) {
                accountValue = document.getElementById(field).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{
                alert('请先选择客户再选择联系人')
            }
        }
        var dataLinesJson;
        function replaceSearchContactLookup() {
            conList = JSON.parse('{!conListJson}');
            dataLinesJson = JSON.parse('{!dataLinesJson}');
            console.log('dataLinesJson = ' + dataLinesJson);
            for(var i = 0;i<dataLinesJson.length;i++){
                //if(document.getElementById('allpage:allForm:allBlock:lines:'+i+':customer') != null){
                let contactHtmlString = '<img src="/img/s.gif" onclick="searchContact(\'allPage:allForm:contactId\',\'allPage:allForm:allBlock:lines:'+i+':customer_lkid\',\'allPage:allForm:allBlock:lines:'+i+':contact_lkid\',\'allPage:allForm:allBlock:lines:'+i+':contact\')" alt="Reference Document Number Lookup" class="lookupIcon"  title="Reference Document Number Lookup (New Window)"/>';
                let lookUpNode = htmlToElement(contactHtmlString);
                console.log(lookUpNode);
                let parentNode = document.getElementById('allPage:allForm:allBlock:lines:'+i+':contact').parentNode;
                //parentNode.appendChild(lookUpNode);
                parentNode.replaceChild(lookUpNode, document.getElementById('allPage:allForm:allBlock:lines:'+i+':contact').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 closePopupWindow() {
            if (null != newSearchContactWindow) {
                newSearchContactWindow.close();
            }
            contactInfoStr = document.getElementById('allPage:allForm:contactId').value;
            console.log('closePopup:'+contactInfoStr);
            let contactInfo = JSON.parse(contactInfoStr);
            let contactNodeId = conValue;
            document.getElementById(contactNodeId).value = contactInfo.ContactId;
            document.getElementById(closeField).value = contactInfo.Name;
        }
        function DecryptAll(){
            let dataIds = [];
            //"{!conList}".each((i,e)=>{
            //    console.log('------------------')
            //    console.log(e);
            //    let v = "{!conList}"[i].contactIdValue;
            //    if (v) {
            //        dataIds.push(v);
            //    }
            //});
            conList = JSON.parse('{!conListJson}');
            if(conList){
                for(var i=0 ;i<conList.length;i++){
                    if(conList[i]!=null){
                        let v = conList[i].contactIdValue;
                        if (v) {
                            dataIds.push(v);
                        }
                    }
                }
            }
            Decrypt(dataIds);
        }
        j$(function(){
            DecryptAll();
        })
        function Decrypt(dataIds){
            let Foo = function(){
                for (const id in dataIds) {
                    if (aws_data.hasOwnProperty(dataIds[id])) {
                        let d = aws_data[dataIds[id]];
                        let $e =j$("[aws-id='"+d.dataId+ "']");
                        //$e.html(d[$e.attr("aws-id")]);
                        $e.each(function(i,e){
                            j$(e).val(d.lastName);
                        })
                    }
                }
            }
            let ids = [];
            //for (const id in dataIds) {
            //    if (!aws_data.hasOwnProperty(id)) {
            //        ids.push(id);
            //    }
            //}
            for(var i =0 ;i<dataIds.length;i++){
                if (!aws_data.hasOwnProperty(dataIds[i])) {
                    ids.push(dataIds[i]);
                }
            }
            if (ids.length > 0) {
                blockme();
                AWSService.search(staticResourceContact.searchUrl,
                JSON.stringify({
                    "dataIds":ids
                }),
                function(data){
                    unblockUI();
                    if(data.object && data.object.length > 0){
                        for(let d in data.object){
                            console.log('----------------')
                            console.log(d);
                            if(data.object[d].dataId){
                                aws_data[data.object[d].dataId] = data.object[d];
                            }
                        }
                        Foo();
                    }
                },
                staticResourceContact.token);
            }else{
                Foo();
            }
        }
        // Update 20220317 By Yang Kaiyu End
        function saveJs() {
        if(confirm('联系人和客户为必填信息,如果为空将不保存此条记录,是否已确认所有需要保存的信息该字段都不为空?')){
            blockme();
            updateUser();
        }
    }
}
</script>
    </script>
<style type="text/css">
    .dateFormat{
        display: none;
    }
</style>
    <style type="text/css">
        .dateFormat{
            display: none;
        }
    </style>
    <apex:form id="allForm">
        <!-- Update 20220317 By Yang Kaiyu Start -->
         <apex:inputHidden value="{!contactId}" id="contactId" />
         <!-- Update 20220317 By Yang Kaiyu End -->
         <apex:actionFunction name="updateUser" action="{!updateUser}" rerender="allForm,message,allPanel" onComplete="unblockUI();"></apex:actionFunction>
         <apex:outputPanel id="message">
            <apex:messages />
@@ -42,23 +196,37 @@
                    <div style="overflow: scroll;height: 300px;width: 1260px; ">
                       <apex:variable value="{!1}" var="cnt" />
                    <apex:repeat value="{!dataLines}" var="line" id="lines">
                                <div style="width: 1260px;">
                        {!$ObjectType.loaner_user__c.fields.Customer__c.label}:
                        <apex:inputField value="{!line.Customer__c}" />
                        <div style="width: 1260px;">
                            {!$ObjectType.loaner_user__c.fields.Customer__c.label}:
                            <!-- Update 20220317 By Yang Kaiyu Start -->
                            <apex:inputField id="customer" value="{!line.Customer__c}" />
                            <!-- Update 20220317 By Yang Kaiyu End -->
                               {!$ObjectType.loaner_user__c.fields.Contact__c.label}:
                               <apex:inputField value="{!line.Contact__c}" />
                            <!-- Update 20220317 By Yang Kaiyu Start -->
                               <apex:inputField id="contact"  value="{!line.Contact__c}" html-aws-id="{!line.Contact__r.AWS_Data_Id__c}" />
                            <!-- <apex:inputText id="contact" html-aws-id="{!line.Contact__r.AWS_Data_Id__c}" disabled="false" value="{!line.Contact__r.LastName}" ></apex:inputText>                       -->
                            <!-- Update 20220317 By Yang Kaiyu End -->
                               {!$ObjectType.loaner_user__c.fields.FromThePeriod__c.label}:
                               <apex:inputField value="{!line.FromThePeriod__c}"/>
                               {!$ObjectType.loaner_user__c.fields.EndThePeriod__c.label}:
                               <apex:inputField value="{!line.EndThePeriod__c}"/>
                        {!$ObjectType.loaner_user__c.fields.Follow_UP_Opp__c.label}:
                        <apex:inputField value="{!line.Follow_UP_Opp__c}"/>
                            {!$ObjectType.loaner_user__c.fields.Follow_UP_Opp__c.label}:
                            <apex:inputField value="{!line.Follow_UP_Opp__c}"/>
                               {!$ObjectType.loaner_user__c.fields.Remarks__c.label}:
                               <apex:inputField value="{!line.Remarks__c}"/>
                               <apex:variable value="{!cnt + 1}" var="cnt" />
                           </div>
                    </apex:repeat>
                    <!-- Update 20220317 By Yang Kaiyu Start -->
                    <script>
                        sfdcPage.appendToOnloadQueue(function () {
                            //Replace Vlookup Field
                            replaceSearchContactLookup();
                        })
                    </script>
                    <!-- Update 20220317 By Yang Kaiyu End -->
                </div>
            </apex:pageBlock>
force-app/main/default/pages/SSBDContractFileUploadPage.page
New file
@@ -0,0 +1,202 @@
<!-- 该页面用于Lead对象上传PDF,未来如果要添加其他对象的上传PDF功能,复制该页面,将**standardController**修改为其他对象API名称即可 -->
<apex:page standardController="Order" 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) {
            // debugger
            console.log('fileUrl---'+fileUrl);
            // let encodefileUrl =encodeURIComponent(fileUrl);
            // console.log('encodefileUrl---'+encodefileUrl);
            window.open(fileUrl,'_blank');
            // debugger
        }
    </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="附件" 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:relatedList  list="CombinedAttachments" id="Notes">
        <apex:facet name="NoteHeader" ></apex:facet>
    </apex:relatedList>
    <script>
        const element = document.getElementsByName('attachFile')[0];
        element.remove();
        document.getElementById('page:Notes_title').innerText = '备注';
    </script>
</apex:page>
force-app/main/default/pages/SSBDContractFileUploadPage.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>SSBDContractFileUploadPage</label>
</ApexPage>
force-app/main/default/pages/SWOFileUploadPage.page
New file
@@ -0,0 +1,184 @@
<!-- 该页面用于Lead对象上传PDF,未来如果要添加其他对象的上传PDF功能,复制该页面,将**standardController**修改为其他对象API名称即可 -->
<apex:page standardController="SWO__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) {
            AWSService.post(staticResources.updateUrl, JSON.stringify({
                "txId":transId,
                "sfRecordId":"",
                "isSuccess":isSuccess
            }), function(result){
                console.log("confirmTrans-" + JSON.stringify(data));
                document.getElementById("file").files[0].name = '';
                enableButtonStatus();
                refreshFiles();
            }, staticResources.token);
        }
        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/SWOFileUploadPage.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>SWOFileUploadPage</label>
</ApexPage>
force-app/main/default/pages/SearchAWSContactByNamePage.page
New file
@@ -0,0 +1,208 @@
<apex:page controller="SearchContactController" id="page">
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}" />
    <apex:includeScript value="{! URLFOR($Resource.AWSService, 'AWSService.js') }" />
    <apex:includeScript value="{!URLFOR($Resource.jquery183minjs)}" />
    <apex:includeScript value="{!URLFOR($Resource.PleaseWaitDialog)}" />
    <apex:stylesheet value="{!URLFOR($Resource.blockUIcss)}" />
    <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 = '';
            function searchAWSContact(){
                console.log('Search process!');
                //1. reset table;
                blockme();
                resetTable();
                //2. get contact name value
                searchContactName = document.getElementById('page:form:lksrch').value;
                //3. check searchContactName.length>=2
                if(searchContactName.length>=2){
                    queryLeadFromAWS();
                }else{
                    alert("请输入至少2个关键字");
                    unblockUI();
                }
            }
            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 = [];
                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) => {
                    console.log('JSON Result from aws:'+JSON.stringify(result));
                    if(result.object&&result.object.length>0){
                        initContactTable(result);
                    }else{
                        unblockUI();
                        alert('没有查到该联系人')
                    }
                })
            }
            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;
                window.open('\\'+obj.currentTarget.id,'_blank');
                console.log('Contact Infor:'+JSON.stringify(contactInfo));
            }
            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');
                let colsHeader = ['姓名','客户名称','邮箱', '电话','手机号'];
                tableBody.appendChild(headerTR);
                for (let i = 0; i < colsHeader.length; i++) {
                    let td = document.createElement('TH');
                    td.width = '75';
                    td.appendChild(document.createTextNode(colsHeader[i]));
                    headerTR.appendChild(td);
                }
                //3. Init the AWS data
                for (let i = 0; i < contactInfoList.length; i++) {
                    let contactInfoTemp = contactInfoList[i]
                    if(contactsInfo[contactInfoTemp.AWSDataId] != null){
                        let tr = document.createElement('TR');
                        tableBody.appendChild(tr);
                        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]]!=null?contactInfoTemp[cols[j]]:''));
                            if (cols[j] == 'Name') {
                                td.addEventListener("click", function (obj) {
                                    redirectToParentPage(obj);
                                });
                            }
                            tr.appendChild(td);
                        }
                    }
                }
                myTableDiv.appendChild(table);
                unblockUI();
            }
            function initContactTable(data) {
                let cols = ['Name','AccountName','Email', 'Phone','MobilePhone'];
                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.MobilePhone = data.object[i].mobilePhone;
                        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('Contact Info from AWS:'+JSON.stringify(contactInfoList));
                //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,"\""));
                                console.log('Contact Info from SF:'+JSON.stringify(contactsInfo));
                                if(Object.keys(contactsInfo).length>0){
                                    for(let i=0;i<contactInfoList.length;i++){
                                        let contactFromSF = contactsInfo[contactInfoList[i]['AWSDataId']];
                                        if(contactFromSF){
                                            contactInfoList[i].sfRecordId = contactFromSF['Id'];
                                            contactInfoList[i].AccountName = contactFromSF['Account']['Name'];
                                        }
                                    }
                                }
                                refreshTable(cols,contactInfoList);
                            }else{
                                alert('没查询到该联系人');
                                console.log('No result');
                                refreshTable(cols,[]);
                            }
                        }
                    },
                    { 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>联系人搜索</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">请输入联系人的姓名进行搜索。
                    </div>
                </div>
            </div>
            <div id="QueryResult">
            </div>
        </apex:form>
    </body>
</apex:page>
force-app/main/default/pages/SearchAWSContactByNamePage.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>SearchAWSContactByNamePage</label>
</ApexPage>
force-app/main/default/triggers/FileAddressTrigger.trigger
New file
@@ -0,0 +1,15 @@
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.isFuture()||System.isBatch())){
        system.debug('DeleteFiles Value:'+JSON.serialize(deleteFiles));
        if(!Test.isRunningTest()){
            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>