Salesfroce重写记录类型选择页面 - 项目实战

313 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

案例一

场景描述

在做订单管理的时候,订单的记录类型有很多,不同的用户对不同的记录类型的访问权限大不一样,比如有5个订单记录类型,其中只有促销订单的记录类型不允许用户从Order Tab处创建,这时如果沿用标准的记录类型选择页面,用户体验终究不好。所以需要重写订单记录类型选择页面来过滤掉促销订单这种特殊情况,以下是解决方案。

解决方案

Apex Code

public class ACC_OrderRecordTypeSelection {
	public List<String> rtIds {get;set;}
	public List<RecordType> rtList {get;set;}
    public List<SelectOption> listViewOptions {get;set;}
	public String filterId {get;set;}

	public ACC_OrderRecordTypeSelection(ApexPages.StandardController controller) {
		rtIds = new List<String>();
		rtList = new List<RecordType>();
		listViewOptions = new List<SelectOption>();
		List<RecordTypeInfo> rtInfoList = Schema.Order.SObjectType.getDescribe().getRecordTypeInfos();
		System.debug('rtInfoList: ' + rtInfoList);
		// Judge whether the order record type is customized
		if(rtInfoList.size() > 0 && rtInfoList.size() == 1 && rtInfoList[0].getName().equals(Label.ACC_Order_Master_RT_Label_Name)) {
        	listViewOptions.add(new SelectOption(rtInfoList[0].getRecordTypeId(), rtInfoList[0].getName()));
        	rtIds.add(rtInfoList[0].getRecordTypeId());
        }else {
        	for(RecordTypeInfo info: rtInfoList) {
			    System.debug('info: ' + info);
			    if(info.isAvailable()) {
			    	 //filter recordtype which is not equal to promotion order
			    	if(info.getName().equals(Label.ACC_Promotion_Order_RecordType_Label_Name) || info.getName().equals(Label.ACC_Order_Master_RT_Label_Name)) {
			    		continue;
		    		}else {
		    			listViewOptions.add(new SelectOption(info.getRecordTypeId(), info.getName()));
		    			rtIds.add(info.getRecordTypeId());
		    		}
			    }
	        }
	        if(rtIds.size() > 0) {
	        	rtList = [SELECT Name, Description FROM RecordType WHERE Id IN :rtIds];
	        }
		}
	}
	public PageReference ACC_CreateOrder() {
    	System.debug('filterId: ' + filterId);
    	//return new PageReference('/801/e?retURL=%2F801%2Fo&RecordType='+ filterId +'&ent=Order');
    	//return new PageReference('/801/e?&RecordType='+ filterId);
    	PageReference newPage = new PageReference('/801/e?&RecordType='+ filterId +'+&retURL=/apex/ACC_OrderRecordTypeSelection&ent=Order&nooverride=1');
    	return newPage;
    }
}

Visualforce Page

<apex:page standardController="Order" extensions="ACC_OrderRecordTypeSelection" sidebar="false">
	<style>
		.noteMsg {margin-bottom: 16px;font-size: 109%;}
		.tableHeader {background: #f2f3f3;}
	</style>
	<apex:sectionHeader title="{! $Label.ACC_New_Order_Label}" subtitle="{! $Label.ACC_Select_Order_Record_Type_Label}" help="https://help.salesforce.com/articleView?id=permissions_record_type_access.htm"/>
	<apex:outputPanel layout="block" styleClass="noteMsg">{! $Label.ACC_Order_RecordType_Tip_Msg_Label}</apex:outputPanel>
	<apex:form>
		<apex:pageBlock title="{! $Label.ACC_Order_RecordType_Table_Title_Label}">
			<apex:pageBlockButtons location="bottom">
				<apex:commandButton value="{! $Label.ACC_Continue_Label}" action="{!ACC_CreateOrder}"/>
				<!-- call standard cancel action -->
				<apex:commandButton value="{! $Label.ACC_Cancel_Label}" action="{!cancel}"/>
			</apex:pageBlockButtons>
			<apex:pageBlockSection>
				<apex:selectList value="{! filterId}" size="1">  
					<apex:outputLabel style="margin-right: 16px;"><h3>{! $Label.ACC_RecordType_Of_New_Record_Label}</h3></apex:outputLabel>
                	<apex:selectOptions value="{! listViewOptions}"/>  
	            </apex:selectList> 
			</apex:pageBlockSection>
		</apex:pageBlock>
		<h3 style="margin: 20px 0 10px;display: block;">{! $Label.ACC_Available_Label}</h3>
		<apex:dataTable value="{!rtList}" var="rt" headerClass="tableHeader" border="1" cellpadding="4" cellspacing="0" style="border-color: #fff;">
	        <apex:column headerValue="{! $Label.ACC_Record_Type_Name_Label}"><h3>{!rt.Name}</h3></apex:column>
	        <apex:column headerValue="{! $Label.ACC_Description_Label}">{!rt.Description}</apex:column>
	    </apex:dataTable>
	</apex:form>
</apex:page>

效果预览

其他考虑

  1. 如果需要做国际化,那么页面上的文字描述需要翻译,推荐使用Custom Label;
  2. 你可能会遇到点击continue按钮,重写的按钮跳转不过去,请处理url,参照代码加参数 - '&nooverride=1';
  3. 重写后需要将每个简档都分配apex/vf权限,否则会显示无权限;
  4. 其他问题,请在评论区留下你的

潜在风险

如果使用自定义按钮创建该对象记录时,一定要在url上拼接:"&nooverride=1",否则会先跳转到记录类型选择页面,之前url传到参数将不存在。

案例二

场景描述

当创建Case时,需要为一个自定义的Open Date字段填充一个当前时间。[Source: Convoy]

解决方案:URL传参

  1. Override Standard 'New' Button with a visualforce page(visualforce必须扩展标准的页面才能被选中 - 需要有StandardController="Case" and Extensions="");\
  2. 在自定义页面中的action属性指定跳转页面的url;这时你得考虑如何指定记录类型

示例代码v1.0

public class StdCaseController {
    private final Case caseItem;
    public StdCaseController(ApexPages.StandardController stdController) {
        caseItem = (Case)stdController.getRecord();
    }
    public PageReference redictStdCasePage() {
        String caseOpenNameVal = '00Np0000001sUmc';
        String openDate = System.now().format();
        System.debug('openDate:' + openDate);
        String recordtypeId = '012p0000000B5IC';
        PageReference pf = new PageReference('/500/e?retURL=%2F500%3Ffcf%3D00B90000007IW4N&RecordType='+ recordtypeId +'&'+ caseOpenNameVal +'='+ openDate +'&ent=Case&nooverride=1');
        return pf;
    } 
}

示例代码v2.0

public class StdCaseController {
    private final Case caseItem;
    public StdCaseController(ApexPages.StandardController stdController) {
        caseItem = (Case)stdController.getRecord();
    }

    public PageReference redirect(){
        String openDate = System.now().format();
        String param = getParameters() + '&00Np0000001sUmc='+openDate;
        return new PageReference('/500/e?nooverride=1&'+param); 
    }

	// Inherit previous parameters, more imporatntly, RecordType parameter!
    private String getParameters(){
        string param = '';
        Map<String, String> strMap = ApexPages.currentPage().getParameters();
        String[] keys = new String[]{'RecordType', 'retURL', 'cancelURL'};
        for(String s : keys){
            if(strMap.containsKey(S)) param += s + '=' + strMap.get(s) + '&';
        }
        if(param.length() > 0) param = param.substring(0, param.length()-1);
        return param;
    }
}