SAP CRM呼叫中心里回复社交媒体信息的实现源代码
我们知道,在SAP CRM呼叫中心的社交媒体集成方案里,如果在系统里配置了某个twitter账号,那么twitter网站上@了该账号的那些tweet,都会自动被抓到SAP CRM呼叫中心中去供座席处理。
上图的@了AndrewPang6这个账号的测试tweet,抓取到SAP CRM呼叫中心后的界面如下。呼叫中心的座席,在CRM系统里点击Reply按钮即可回复。
客户打开tweeter网站,即可看到该回复。
下面是这个功能的实现代码:
<%@page language="abap" %>
<%@extension name="thtmlb" prefix="thtmlb" %>
<%@extension name="chtmlb" prefix="chtmlb" %>
<%@extension name="bsp" prefix="bsp" %>
<%
data: lv_send_btn type string.
data: lv_title_prefix type string,
lv_replyid type string.
lv_send_btn = cl_wd_utilities=>get_otr_text_by_alias( 'CRM_UIU_SOC_SMC/SEND_BUTTON' ). "#EC NOTEXT.
lv_replyid = '_socialpost_struct.content'.
lv_title_prefix = cl_wd_utilities=>get_otr_text_by_alias( 'CRM_UIU_SOC_SMC/COUNTER_TXT' ). "#EC NOTEXT.
lv_title_prefix = lv_title_prefix && ':'.
lv_replyid = controller->component_id && lv_replyid.
%>
<chtmlb:config displayMode = "<%= controller->view_group_context->is_view_in_display_mode( controller ) %>"
mode = "RUNTIME"
xml = "<%= controller->configuration_descr->get_config_data( ) %>" />
<p id="COUNTER_TXT" style="margin-left: 8px; margin-top: 1px; margin-bottom: 4px; margin-right: 8px; color:rgb(102,102,102)"></p>
<p>
<thtmlb:button design = "EMPHASIZED"
id = "SEND_BTN"
onClick = "send"
text = "<%= lv_send_btn %>" />
</P>
<script type="text/javascript">
var content;
var counter;
var cur_pos;
function forwardStdResponseText(reqObj) {
insertText(reqObj);
}
function forwardStdResponseTextDelayed(reqObj) {
insertText(reqObj, true);
}
function insertText(reqObj, delayed) {
var textcontent = reqObj.request.responseText;
if (!delayed){
insertTextIntoTextEditor( textcontent);
}else{
<%--restoreBTFCursorPosition();
insertTextIntoTextEditor( textcontent);--%>
document.getElementById( "<%= lv_replyid %>" ).value = document.getElementById( "<%= lv_replyid %>" ).value + reqObj.request.responseText;
}
refreshCounter();
}
function TrimLeadingSpace(texttotrim)
{
var currchar;
var spaceindex = 0;
currchar = texttotrim.substr(0, 1);
while(currchar==" ")
{
spaceindex = spaceindex + 1;
currchar = texttotrim.substr(spaceindex, 1);
}
var substrlen = texttotrim.length - spaceindex;
var trimmedtext = texttotrim.substr(spaceindex, substrlen);
alert(trimmedtext);
return trimmedtext;
}
function storeBTFCursorPosition(){
var cursorPos = 0;
var textarea1 = document.getElementById("<%= lv_replyid %>");
var range;
var textvalue;
textvalue = textarea1.value;
textarea1.focus();
range = document.selection.createRange();
range.moveStart('character', -textarea1.value.length);
var trimmedtxt = TrimLeadingSpace(range.text);
var spacefromuser = textvalue.search(trimmedtxt);
cursorPos = spacefromuser + trimmedtxt.length;
alert(spacefromuser);
alert(trimmedtxt.length);
return cursorPos;
}
function restoreBTFCursorPosition(){
var texta1 = document.getElementById("<%= lv_replyid %>");
var range;
var curpos = cur_pos;
texta1.focus();
range = document.selection.createRange();
range.moveStart( 'character', texta1.value.length );
range.moveEnd( 'character', texta1.value.length );
range.moveStart( 'character', curpos );
range.moveEnd( 'character', 0 );
range.select();
}
function insertTextIntoTextEditor( textToInsert ){
var text_area = document.getElementById( "<%= lv_replyid %>" );
text_area.focus();
if(document.selection)
{
document.selection.createRange().text = textToInsert;
}
}
<%-- below functions are for, reply text counter implementation --%>
function refreshCounter()
{
var sCount = "<%= lv_title_prefix %>" + content.value.length;
counter.innerHTML = sCount;
}
function fillTitle()
{
var textvalue;
textvalue = document.getElementById("<%= lv_replyid %>").value;
counter.innerHTML = "<%= lv_title_prefix %>" + textvalue.length;
}
if( "<%= controller->mv_switch_on %>" == "X" )
{
content = document.getElementById("<%= lv_replyid %>");
counter = document.getElementById("COUNTER_TXT");
if( content != null )
{
content.onkeyup = refreshCounter;
content.onmouseout = refreshCounter;
content.onmousemove = refreshCounter;
}
fillTitle();
}
</script>
<%
DATA: ls_header type CRMT_THTMLB_AREA_FRAME_HEAD.
ls_header-title = 'Conversation History'.
%>
<thtmlb:splitter splitterPosition = "65%"
height = "100%" >
<thtmlb:grid cellSpacing = "0"
columnSize = "2"
height = "100%"
rowSize = "1"
width = "100%" >
<thtmlb:gridCell colSpan = "1"
columnIndex = "1"
rowIndex = "1"
height = "100%"
rowSpan = "1" >
<thtmlb:splitterCell minSize = "20%"
vAlign = "top"
align = "left" >
<bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'PostDetails' ) %>"
url = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'PostDetails' ) %>" />
<bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'OverviewPage' ) %>"
url = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'OverviewPage' ) %>" />
<div id = "div1" style="display:block; margin-top: 10px">
<thtmlb:areaFrame id = "areaFrame1"
header = "<%= ls_header %>"
isCollapsible = "true"
checkContent = "true"
lateRendering = "true" >
<thtmlb:areaFrameBody contentBorder="false" >
<bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'ConversationHistory' ) %>"
url = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'ConversationHistory' ) %>" />
</thtmlb:areaFrameBody>
</thtmlb:areaFrame>
</div>
</thtmlb:splitterCell>
</thtmlb:gridCell>
<thtmlb:gridCell colSpan = "1"
columnIndex = "2"
rowIndex = "1"
height = "100%"
rowSpan = "1" >
<thtmlb:splitterCell minSize = "20%"
vAlign = "top"
align = "left" >
<bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'PostDetails' ) %>"
url = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'PostDetails' ) %>" />
</thtmlb:splitterCell>
</thtmlb:gridCell>
</thtmlb:grid>
</thtmlb:splitter>
<%@page language="abap" %>
<%@extension name="thtmlb" prefix="thtmlb" %>
<%@extension name="chtmlb" prefix="chtmlb" %>
<%@extension name="bsp" prefix="bsp" %>
<%
DATA: ls_header type CRMT_THTMLB_AREA_FRAME_HEAD.
IF controller->MV_CONV_HISTORY_SWITCH_ON = abap_true.
ls_header-title = cl_wd_utilities=>get_otr_text_by_alias( 'CRM_UIU_SOC_SMC/REPLY_CONV_HISTORY' ).
ENDIF.
%>
<thtmlb:grid cellSpacing = "0"
columnSize = "1"
height = "100%"
rowSize = "3"
width = "100%" >
<thtmlb:gridCell colSpan = "1"
columnIndex = "1"
rowIndex = "1"
height = "100%"
rowSpan = "1" >
<bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'PostDetails' ) %>"
url = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'PostDetails' ) %>" />
</thtmlb:gridCell>
<thtmlb:gridCell colSpan = "1"
columnIndex = "1"
rowIndex = "2"
height = "100%"
rowSpan = "1" >
<bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'OverviewPage' ) %>"
url = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'OverviewPage' ) %>" />
</thtmlb:gridCell>
<%
IF controller->MV_CONV_HISTORY_SWITCH_ON eq abap_true.
%>
<thtmlb:gridCell colSpan = "1"
columnIndex = "1"
rowIndex = "3"
height = "100%"
rowSpan = "1" >
<div style="display:block; margin-top: 5px">
<thtmlb:areaFrame id = "areaFrame1"
header = "<%= ls_header %>"
isCollapsible = "true"
checkContent = "true"
lateRendering = "true" >
<thtmlb:areaFrameBody contentBorder="false" >
<bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'ConversationHistory' ) %>"
url = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'ConversationHistory' ) %>" />
</thtmlb:areaFrameBody>
</thtmlb:areaFrame>
</thtmlb:gridCell>
<%
ENDIF.
%>
</thtmlb:grid>
在使用reply页面, standard response的search 按钮搜索并apply mail form 内容至editor中已有文本的中间位置时,需要通过storeBTFCursorPosition
保存点击search 按钮时光标的位置。该位置即为mail form内容的插入出。
在初始设计中使用range.moveStart来计算光标位置。设想方式为,当move的数值超出文本长度时,该方法只返回实际移动位置,即光标距离文本开始位置的距离。
在实际测试中发现,该方法的返回值不确定。光标处于某些位置时,返回值与期望一致。但是在某些位置,返回值与期望有差别。通过alert range.text的内容发现,
出现不一致的情形时,原因是因为range.text中包含大量的空格符,这些空格符也被计算成range.text的文本长度。从而导致数值不准确。
解决办法
- 仍然使用movestart获取range的text内容(包含空格)
- 去除range的text当中包含的leading 空格。注意在去除leading 空格时,会出现一种情况,就是用户本身在文本开始输入了空格,这些空格会一并去除。
- 用string的search方法找到step 2.中去除空格后的文本在原始文本当中的位置。实际上就是计算用户在文本开始部分自己输入的空格数量。
- 加上range的text长度(去除leading 空格),即为光标的位置
要获取更多Jerry的原创文章,请关注公众号"汪子熙":