问题
The new version of the standard webchat channel ("gemini") stripped out all of the formatting. I was able to replicate most of the old interface via tweaks in the botframework-webchat implementation, but I cannot get the adaptive card formatting to match. With the general formatting I was able to get it close, and the adaptiveCardHostConfig tweaks shown here on Github got a bit closer, but I still can't figure out how to replicate it. Specifically, the chat bubble (which is gray in my implementation) no longer appears behind the adaptive card. This is especially noticeable for carousels, where it used to be one "bubble" with multiple cards and is now discrete cards. Furthermore, the buttons are no longer interactive (blue border used to appear on mouseover), and the bublle "nub" is absent. Please see below for examples. Note that I DO know how to make the background for the card itself gray to match the bubbles, but that is not the look that I want or that displayed previously.
In summary, I'm asking
- How can I format the gray background like was present in the previous version.
- How can I add the bubble nub to the card (or perhaps more accurately, make the card appear inside a bubble).
- How can I make the buttons on the adaptive card interactive
Single Card (new on left, old on right)
Carousel (new on left, old on right)
And here is the website code
<!DOCTYPE html>
<html>
<head>
<title>Support Bot</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<style>
html,
body {
height: 100%;
}
body {
margin: 0;
}
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
}
#chatbotTitle {
display: flex;
align-items: center;
height: 40px;
width: 100%;
background-color: #0067CC;
color: #FFFFFF;
font-family: Calibri, Helvetica Neue, Arial, sans-serif;
justify-content: space-between;
}
#webchat {
height: calc(100% - 40px);
width: 100%;
}
.btn {
display: flex;
background-color: white;
border: 1px solid #767676;
color: #0067CC;
text-align: center;
margin: 15px;
}
.btn:hover {
border-color: #444444;
}
.btn:active {
background-color: #CCCCCC;
}
</style>
</head>
<body>
<div id="chatbotTitle"><h3 style="padding-left:10px;">Support Bot</h3><button class="btn" id="transcriptButton">Email Transcript</button></div>
<div id="webchat" role="main"></div>
<script>
let interval;
var PageTitleNotification = {
Vars:{
OriginalTitle: document.title,
Interval: null
},
On: function(notification, intervalSpeed){
var _this = this;
_this.Vars.Interval = setInterval(function(){
document.title = (_this.Vars.OriginalTitle == document.title)
? notification
: _this.Vars.OriginalTitle;
}, (intervalSpeed) ? intervalSpeed : 1000);
},
Off: function(){
clearInterval(this.Vars.Interval);
document.title = this.Vars.OriginalTitle;
}
}
// We are using a customized store to add hooks to connect event
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'WEB_CHAT/SEND_MESSAGE') {
// Message sent by the user
PageTitleNotification.Off();
clearTimeout(interval);
} else if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY' && action.payload.activity.name !== "inactive") {
// Message sent by the bot
clearInterval(interval);
interval = setTimeout(() => {
// Change title to flash the page
PageTitleNotification.On('Are you still there?');
// Notify bot the user has been inactive
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'inactive',
value: ''
}
});
}, 300000)
}
return next(action);
});
const adaptiveCardHostConfig = {
"spacing": {
"small": 3,
"default": 8,
"medium": 20,
"large": 30,
"extraLarge": 40,
"padding": 10
},
"separator": {
"lineThickness": 1,
"lineColor": "#EEEEEE"
},
"supportsInteractivity": true,
"fontTypes": {
"default": {
"fontFamily": "Calibri, sans-serif",
"fontSizes": {
"small": 12,
"default": 14,
"medium": 17,
"large": 21,
"extraLarge": 26
},
"fontWeights": {
"lighter": 200,
"default": 400,
"bolder": 600
}
},
"monospace": {
"fontFamily": "'Courier New', Courier, monospace",
"fontSizes": {
"small": 12,
"default": 14,
"medium": 17,
"large": 21,
"extraLarge": 26
},
"fontWeights": {
"lighter": 200,
"default": 400,
"bolder": 600
}
}
},
"containerStyles": {
"default": {
"backgroundColor": "#FFFFFF",
"foregroundColors": {
"default": {
"default": "#000000",
"subtle": "#767676"
},
"accent": {
"default": "#0063B1",
"subtle": "#0063B1"
},
"attention": {
"default": "#FF0000",
"subtle": "#DDFF0000"
},
"good": {
"default": "#54a254",
"subtle": "#DD54a254"
},
"warning": {
"default": "#c3ab23",
"subtle": "#DDc3ab23"
}
}
},
"emphasis": {
"backgroundColor": "#F0F0F0",
"foregroundColors": {
"default": {
"default": "#000000",
"subtle": "#767676"
},
"accent": {
"default": "#2E89FC",
"subtle": "#882E89FC"
},
"attention": {
"default": "#FF0000",
"subtle": "#DDFF0000"
},
"good": {
"default": "#54a254",
"subtle": "#DD54a254"
},
"warning": {
"default": "#c3ab23",
"subtle": "#DDc3ab23"
}
}
},
"accent": {
"backgroundColor": "#C7DEF9",
"foregroundColors": {
"default": {
"default": "#333333",
"subtle": "#EE333333"
},
"dark": {
"default": "#000000",
"subtle": "#66000000"
},
"light": {
"default": "#FFFFFF",
"subtle": "#33000000"
},
"accent": {
"default": "#2E89FC",
"subtle": "#882E89FC"
},
"attention": {
"default": "#cc3300",
"subtle": "#DDcc3300"
},
"good": {
"default": "#54a254",
"subtle": "#DD54a254"
},
"warning": {
"default": "#e69500",
"subtle": "#DDe69500"
}
}
},
"good": {
"backgroundColor": "#CCFFCC",
"foregroundColors": {
"default": {
"default": "#333333",
"subtle": "#EE333333"
},
"dark": {
"default": "#000000",
"subtle": "#66000000"
},
"light": {
"default": "#FFFFFF",
"subtle": "#33000000"
},
"accent": {
"default": "#2E89FC",
"subtle": "#882E89FC"
},
"attention": {
"default": "#cc3300",
"subtle": "#DDcc3300"
},
"good": {
"default": "#54a254",
"subtle": "#DD54a254"
},
"warning": {
"default": "#e69500",
"subtle": "#DDe69500"
}
}
},
"attention": {
"backgroundColor": "#FFC5B2",
"foregroundColors": {
"default": {
"default": "#333333",
"subtle": "#EE333333"
},
"dark": {
"default": "#000000",
"subtle": "#66000000"
},
"light": {
"default": "#FFFFFF",
"subtle": "#33000000"
},
"accent": {
"default": "#2E89FC",
"subtle": "#882E89FC"
},
"attention": {
"default": "#cc3300",
"subtle": "#DDcc3300"
},
"good": {
"default": "#54a254",
"subtle": "#DD54a254"
},
"warning": {
"default": "#e69500",
"subtle": "#DDe69500"
}
}
},
"warning": {
"backgroundColor": "#FFE2B2",
"foregroundColors": {
"default": {
"default": "#333333",
"subtle": "#EE333333"
},
"dark": {
"default": "#000000",
"subtle": "#66000000"
},
"light": {
"default": "#FFFFFF",
"subtle": "#33000000"
},
"accent": {
"default": "#2E89FC",
"subtle": "#882E89FC"
},
"attention": {
"default": "#cc3300",
"subtle": "#DDcc3300"
},
"good": {
"default": "#54a254",
"subtle": "#DD54a254"
},
"warning": {
"default": "#e69500",
"subtle": "#DDe69500"
}
}
}
},
"imageSizes": {
"small": 40,
"medium": 80,
"large": 160
},
"actions": {
"maxActions": 100,
"spacing": "default",
"buttonSpacing": 8,
"showCard": {
"actionMode": "inline",
"inlineTopMargin": 8
},
"actionsOrientation": "vertical",
"actionAlignment": "stretch"
},
"adaptiveCard": {
"allowCustomStyle": false
},
"imageSet": {
"imageSize": "medium",
"maxImageHeight": 100
},
"factSet": {
"title": {
"color": "default",
"size": "default",
"isSubtle": false,
"weight": "bolder",
"wrap": true,
"maxWidth": 150
},
"value": {
"color": "default",
"size": "default",
"isSubtle": false,
"weight": "default",
"wrap": true
},
"spacing": 8
}
};
window.WebChat.renderWebChat(
{
adaptiveCardHostConfig,
directLine: window.WebChat.createDirectLine({
token: 'MYTOKENHERE'
}),
store: store,
userID: 'userID',
username: 'userName',
locale: 'en-US',
styleOptions: {
botAvatarInitials: 'BOT',
userAvatarInitials: 'USR',
accent: '#0067CC',
backgroundColor: 'White',
cardEmphasisBackgroundColor: '#F0F0F0',
paddingRegular: 10,
paddingWide: 10 * 2,
messageActivityWordBreak: 'break-word',
fontSizeSmall: '80%',
avatarSize: 40,
botAvatarBackgroundColor: '#0067CC',
botAvatarImage: '',
botAvatarInitials: '',
userAvatarBackgroundColor: '#ECEFF1',
userAvatarImage: '',
userAvatarInitials: '',
bubbleBackground: '#ECEFF1',
bubbleBorderColor: '#E6E6E6',
bubbleBorderRadius: 8,
bubbleBorderStyle: 'solid',
bubbleBorderWidth: 1,
bubbleFromUserBackground: '#0067CC',
bubbleFromUserBorderColor: '#E6E6E6',
bubbleFromUserBorderRadius: 8,
bubbleFromUserBorderStyle: 'solid',
bubbleFromUserBorderWidth: 1,
bubbleFromUserNubOffset: 'bottom',
bubbleFromUserNubSize: 10,
bubbleFromUserTextColor: 'White',
bubbleImageHeight: 240,
bubbleMaxWidth: 480,
bubbleMinHeight: 30,
bubbleMinWidth: 250,
bubbleNubOffset: 'bottom',
bubbleNubSize: 10,
bubbleTextColor: 'Black',
markdownRespectCRLF: true,
richCardWrapTitle: false,
rootHeight: '100%',
rootWidth: '100%',
hideScrollToEndButton: false,
hideSendBox: false,
hideUploadButton: true,
microphoneButtonColorOnDictate: '#F33',
sendBoxBackground: 'White',
sendBoxButtonColor: '#767676',
sendBoxButtonColorOnDisabled: '#CCC',
sendBoxButtonColorOnFocus: '#0067CC',
sendBoxButtonColorOnHover: '#0067CC',
sendBoxDisabledTextColor: '#767676', // defaults to subtle
sendBoxHeight: 40,
sendBoxMaxHeight: 200,
sendBoxTextColor: 'Black',
sendBoxBorderBottom: 'solid 5px #DBDEE1',
sendBoxBorderLeft: 'solid 5px #DBDEE1',
sendBoxBorderRight: 'solid 5px #DBDEE1',
sendBoxBorderTop: 'solid 5px #DBDEE1',
sendBoxPlaceholderColor: undefined, // defaults to subtle
sendBoxTextWrap: false,
showSpokenText: false,
suggestedActionBackground: 'White',
suggestedActionBorder: undefined,
suggestedActionBorderColor: '#CCCCCC',
suggestedActionBorderRadius: 0,
suggestedActionBorderStyle: 'solid',
suggestedActionBorderWidth: 1,
suggestedActionDisabledBackground: '#F9F9F9',
suggestedActionDisabledBorder: null,
suggestedActionDisabledBorderColor: '#E6E6E6',
suggestedActionDisabledBorderStyle: 'solid',
suggestedActionDisabledBorderWidth: 1,
suggestedActionDisabledTextColor: '#767676',
suggestedActionHeight: 30,
suggestedActionImageHeight: 20,
suggestedActionLayout: 'carousel',
suggestedActionTextColor: null,
groupTimestamp: false,
sendTimeout: 20000,
sendTimeoutForAttachments: 120000,
timestampColor: '#767676',
timestampFormat: 'relative',
transcriptOverlayButtonBackground: 'rgba(0, 0, 0, .6)',
transcriptOverlayButtonBackgroundOnFocus: 'rgba(0, 0, 0, .8)',
transcriptOverlayButtonBackgroundOnHover: 'rgba(0, 0, 0, .8)',
transcriptOverlayButtonColor: 'White',
transcriptOverlayButtonColorOnFocus: 'White',
transcriptOverlayButtonColorOnHover: 'White',
typingAnimationBackgroundImage: null,
typingAnimationDuration: 5000,
typingAnimationHeight: 20,
typingAnimationWidth: 64,
subtle: '#767676'
}
},
document.getElementById('webchat')
);
document.querySelector('#transcriptButton').addEventListener('click', () => {
store.dispatch({
type: 'WEB_CHAT/SEND_MESSAGE',
payload: { text: 'Email me a transcript' }
});
});
</script>
</body>
</html>
回答1:
Web Chat and Adaptive Cards are both open source, so it's a good idea to download their source code if you want to figure out how they work. In the Web Chat repo you can switch to the v3 branch to see how v3 works. Web Chat uses the Adaptive Cards JavaScript SDK, and the code that handles parsing and rendering is in card-elements.ts.
In botchat.css, you can see the styles that create the background you want here:
.wc-message-content { border-radius: 2px; box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.2); padding: 8px; word-break: break-word; } .wc-message-from-bot .wc-message-content { background-color: #eceff1; color: #000000; }
Those classes aren't used in Web Chat v4, but you can apply it to your attachments and carousels like this:
div.attachment.bubble,
div.content > ul.webchat__carousel__item_indented {
background-color: #eceff1;
color: #000000;
border-radius: 2px;
box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.2);
padding: 8px;
}
I'm being pretty specific with the selector because there's another style that will try to set the padding to 0. You can just use the !important
keyword if you want.
You've already seen that Web Chat doesn't allow bubble nubs on attachments in v4. The line responsible for this is here:
<Bubble className="attachment bubble" fromUser={fromUser} key={index} nub={false}>
You can modify the way activities are rendered using activity middleware according to this sample. In your case you'll want to render an SVG element alongside the activity.
To add hover styles to your buttons, you can again have a look at botchat.css:
.wc-card button:hover { background-color: transparent; border-color: #0078d7; color: #0078d7; }
You can use all three of those declarations or just border-color
:
.ac-adaptiveCard button:hover {
border-color: #0078d7;
}
来源:https://stackoverflow.com/questions/60383301/how-to-format-adaptive-cards-like-the-old-version-of-webchat