/* ============================================================ * lib/components/chat-window.js · 仿微信一对一聊天窗 * 用法: * * // 短数据 * * // 长数据 * 消息类型:text / transfer(转账卡) / time(时间) / divider(分隔) / image / quote * 全部颜色来自 tokens.css 的 --chat-*(双主题自适应)。 * ============================================================ */ (function () { function esc(s) { return String(s == null ? '' : s) .replace(/&/g, '&').replace(//g, '>'); } function nl(s) { return esc(s).replace(/\n/g, '
'); } function parse(el) { if (el.dataset.chat) { try { return JSON.parse(el.dataset.chat); } catch (e) { return null; } } if (el.dataset.ref) { var src = document.querySelector(el.dataset.ref); if (src) { try { return JSON.parse(src.textContent); } catch (e) { return null; } } } return null; } function renderMsg(m) { var side = m.side === 'out' ? 'out' : 'in'; if (m.type === 'time') { return '
' + esc(m.text) + '
'; } if (m.type === 'divider') { return '
' + esc(m.text) + '
'; } // 带气泡的消息 var ava = '
' + esc(m.avatar || (side === 'out' ? '我' : '')) + '
'; var inner = ''; if (m.type === 'transfer') { inner = '
' + '' + esc(m.text || '微信转账') + '' + '' + esc(m.amount || '') + '' + '
'; } else if (m.type === 'image') { inner = '
' + (m.caption ? '
' + esc(m.caption) + '
' : '') + '
'; } else if (m.type === 'quote') { inner = '
' + nl(m.text) + (m.source ? '
' + esc(m.source) + '
' : '') + '
'; } else { var body = nl(m.text); if (m.bold) body = '' + body + ''; inner = '
' + body + '
'; } return '
' + (side === 'in' ? ava + inner : inner + ava) + '
'; } function render(el, d) { if (!d) { el.innerHTML = '
数据缺失
'; return; } var msgs = (d.msgs || []).map(renderMsg).join(''); el.innerHTML = '
' + (d.title || d.subtitle ? ( '
' + esc(d.title || '') + (d.subtitle ? '' + esc(d.subtitle) + '' : '') + '
' ) : '') + '
' + msgs + '
' + (d.footer ? '
' + esc(d.footer) + '
' : '') + '
'; } var ChatWindow = function () { return Reflect.construct(HTMLElement, [], ChatWindow); }; ChatWindow.prototype = Object.create(HTMLElement.prototype); ChatWindow.prototype.constructor = ChatWindow; ChatWindow.prototype.connectedCallback = function () { var self = this; var d = parse(this); if (!d && this.dataset.ref) { // ref 指向的 JSON 可能晚于组件加载,延时再读一次 setTimeout(function () { render(self, parse(self)); }, 0); } else { render(this, d); } }; if (!customElements.get('chat-window')) { customElements.define('chat-window', ChatWindow); } })();