fix: 品牌下发审查修复(esc统一/语料中性化/穿越加固/反向断言动态化)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -30,7 +30,7 @@
|
||||
<div style="display:flex;align-items:center;gap:14px;">
|
||||
<div class="help-content">
|
||||
<div class="help-title">How can we help?</div>
|
||||
<div class="help-description">Ask about pipe specifications, quotations, MOQ, shipping and delivery.</div>
|
||||
<div class="help-description">Ask about products, quotations, MOQ, shipping and delivery.</div>
|
||||
</div>
|
||||
<div class="help-actions">
|
||||
<!-- Task 10: 联系按钮/标题/欢迎语/话题/隐私链接由 chat.js 从
|
||||
|
||||
+6
-10
@@ -86,9 +86,12 @@ var chatBrandReady = (function () {
|
||||
var em = contactHref(emailAttr || b.email || "", "mail");
|
||||
if (emBtn) { if (em) emBtn.href = em; else emBtn.style.display = "none"; }
|
||||
if (b.placeholder) inputEl.placeholder = b.placeholder;
|
||||
var firstMsg = document.querySelector("#messages .message");
|
||||
var bubble = firstMsg && firstMsg.querySelector(".bubble");
|
||||
if (b.welcome) {
|
||||
var bubble = document.querySelector("#messages .message .bubble");
|
||||
if (bubble) bubble.textContent = b.welcome;
|
||||
} else if (firstMsg) {
|
||||
firstMsg.style.display = "none"; // 空 welcome 不渲染空气泡(与挂件行为对齐)
|
||||
}
|
||||
if (Array.isArray(b.topics) && b.topics.length) {
|
||||
var grid = document.querySelector(".popular-topics-grid");
|
||||
@@ -286,15 +289,8 @@ var chatBrandReady = (function () {
|
||||
}
|
||||
});
|
||||
|
||||
// Popular topics buttons(出厂模板的兜底话题;brand 下发后由 applyBrand
|
||||
// 重建,这里的绑定覆盖"brand 失败"路径)
|
||||
var topicBtns = document.querySelectorAll(".popular-topic-btn");
|
||||
topicBtns.forEach(function (btn) {
|
||||
btn.addEventListener("click", function () {
|
||||
var topic = this.getAttribute("data-topic");
|
||||
sendTopicMessage(topic);
|
||||
});
|
||||
});
|
||||
// (出厂模板话题区为空——话题按钮只由 applyBrand 重建并自带绑定,
|
||||
// 无静态兜底绑定段)
|
||||
|
||||
// Task 10: 会话 key 租户化(cc_session_id_<slug>)——brand 落定(成功或
|
||||
// 失败,slug 回退 "default")后才读 key/连 WS,保证同浏览器多租户互不串
|
||||
|
||||
@@ -39,11 +39,10 @@
|
||||
<p><strong>Expected behavior:</strong></p>
|
||||
<ul class="test-list">
|
||||
<li>Invite card appears after 5 seconds</li>
|
||||
<li>Invite card has blue gradient header with robot emoji</li>
|
||||
<li>Three topic buttons: "Get Quotation", "Pipe Specifications" and "Delivery & Shipping"</li>
|
||||
<li>Invite card has brand-color gradient header with robot emoji</li>
|
||||
<li>Topic buttons come from the tenant brand config (<code>/api/public/brand</code> → topics)</li>
|
||||
<li>Action buttons: "Start Chat" and "No Thanks"</li>
|
||||
<li>Click "Get Quotation" → invite closes → chat opens → message auto-sends</li>
|
||||
<li>Click "Pipe Specifications" → invite closes → chat opens → message auto-sends</li>
|
||||
<li>Click a topic button → invite closes → chat opens → message auto-sends</li>
|
||||
<li>Click "Start Chat" → invite closes → chat opens</li>
|
||||
<li>Click "No Thanks" → invite permanently closes</li>
|
||||
<li>Click "No Thanks" or X → refresh → invite stays hidden AND the old card area stays clickable (no invisible overlay; regression 2026-09-01)</li>
|
||||
@@ -55,7 +54,7 @@
|
||||
<div class="info">
|
||||
<h2>Popular Topics in Chat Panel</h2>
|
||||
<ul class="test-list">
|
||||
<li>Chat panel shows "POPULAR TOPICS" section with two buttons</li>
|
||||
<li>Chat panel shows "POPULAR TOPICS" section with the tenant's topic buttons</li>
|
||||
<li>Click topic → message auto-sends → topics section hides</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -108,7 +107,7 @@
|
||||
"data-mobile": "true",
|
||||
"data-debug": "true",
|
||||
"data-whatsapp": "https://wa.me/8613800138000",
|
||||
"data-email": "mailto:demo@hesupipe.com"
|
||||
"data-email": "mailto:demo@example.com"
|
||||
};
|
||||
|
||||
var rebuildLoading = false, rebuildPending = null;
|
||||
@@ -116,6 +115,9 @@
|
||||
// Task 10: host id 已租户化(cc-widget-host-<slug>),按前缀清扫
|
||||
var hosts = document.querySelectorAll('[id^="cc-widget-host-"]');
|
||||
for (var i = 0; i < hosts.length; i++) hosts[i].remove();
|
||||
// 复审: 清掉旧挂件的 debug 钩子——waitForWidget 轮询它,旧钩子残留
|
||||
// 会让重建中的断言误读"新挂件已挂载"
|
||||
try { delete window.__chatWidgetDebug; } catch (e) {}
|
||||
}
|
||||
function rebuildWidget(extra) {
|
||||
if (rebuildLoading) { rebuildPending = extra || {}; return; } // 快速连点:只记最新意图,当前加载完接力重建
|
||||
|
||||
+6
-6
@@ -388,7 +388,7 @@
|
||||
panel.className = "chat-panel";
|
||||
panel.innerHTML = [
|
||||
'<div class="panel-header">',
|
||||
'<div class="avatar"><span class="avatar-emoji">🤖</span><img class="avatar-img" alt="" src="'+avatarUrl+'"></div>',
|
||||
'<div class="avatar"><span class="avatar-emoji">🤖</span><img class="avatar-img" alt="" src="'+esc(avatarUrl)+'"></div>',
|
||||
'<div class="info"><h3>' + esc(title) + '</h3><div class="status">Online now · Usually replies in minutes</div></div>',
|
||||
'<div class="actions">',
|
||||
'<button class="action-btn" aria-label="Minimize">−</button>',
|
||||
@@ -396,7 +396,7 @@
|
||||
'</div></div>',
|
||||
'<div class="ended" id="w-ended">Chat ended. We\'ll be in touch!</div>',
|
||||
'<div class="panel-top">',
|
||||
'<div class="help-block"><div style="display:flex;align-items:center;gap:14px;"><div class="help-content"><div class="help-title">How can we help?</div><div class="help-description">Ask about pipe specifications, quotations, MOQ, shipping and delivery.</div></div><div class="help-actions">' + waBtnHtml + emBtnHtml + '</div></div></div>',
|
||||
'<div class="help-block"><div style="display:flex;align-items:center;gap:14px;"><div class="help-content"><div class="help-title">How can we help?</div><div class="help-description">Ask about products, quotations, MOQ, shipping and delivery.</div></div><div class="help-actions">' + waBtnHtml + emBtnHtml + '</div></div></div>',
|
||||
'</div>',
|
||||
'<div class="chat-separator"></div>',
|
||||
'<div class="panel-messages" id="w-msgs">',
|
||||
@@ -416,10 +416,10 @@
|
||||
'<div class="invite-panel hide">',
|
||||
'<div class="invite-header">',
|
||||
'<div class="invite-icon-wrapper">',
|
||||
'<div class="invite-icon"><span class="avatar-emoji">🤖</span><img class="avatar-img" alt="" src="'+avatarUrl+'"><span class="invite-status-dot"></span></div>',
|
||||
'<div class="invite-icon"><span class="avatar-emoji">🤖</span><img class="avatar-img" alt="" src="'+esc(avatarUrl)+'"><span class="invite-status-dot"></span></div>',
|
||||
'</div>',
|
||||
'<div class="invite-header-content">',
|
||||
'<div class="invite-title">Chat with us for pipe specs, MOQ, delivery timing and quotations.</div>',
|
||||
'<div class="invite-title">Chat with us for products, quotations and delivery.</div>',
|
||||
'</div>',
|
||||
'<div class="invite-header-actions">',
|
||||
'<button class="invite-close-btn" aria-label="Close">',
|
||||
@@ -467,13 +467,13 @@
|
||||
toggleBtn.className = "toggle-btn" + (isMobile ? " mobile" : "");
|
||||
if (isMobile) {
|
||||
toggleBtn.innerHTML = `
|
||||
<div class="mobile-circle"><span class="avatar-emoji">🤖</span><img class="avatar-img" alt="" src="${avatarUrl}"><span class="mobile-dot"></span></div>
|
||||
<div class="mobile-circle"><span class="avatar-emoji">🤖</span><img class="avatar-img" alt="" src="${esc(avatarUrl)}"><span class="mobile-dot"></span></div>
|
||||
<span class="mobile-label">Chat with us</span>
|
||||
`;
|
||||
} else {
|
||||
toggleBtn.innerHTML = `
|
||||
<div class="toggle-avatar-wrap">
|
||||
<div class="toggle-avatar-circle"><span class="avatar-emoji">🤖</span><img class="avatar-img" alt="" src="${avatarUrl}"></div>
|
||||
<div class="toggle-avatar-circle"><span class="avatar-emoji">🤖</span><img class="avatar-img" alt="" src="${esc(avatarUrl)}"></div>
|
||||
<div class="toggle-avatar-dot"></div>
|
||||
</div>
|
||||
<div style="color:white;">
|
||||
|
||||
Reference in New Issue
Block a user