You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2 lines
86 KiB
2 lines
86 KiB
var ChatbotSDK=function(){"use strict";const n="[ChatbotSDK]";let e=!0;const t={},r={info(t,r){e&&console.log(n,t,void 0!==r?r:"")},warn(t,r){e&&console.warn(n,t,void 0!==r?r:"")},error(e,t){console.error(n,e,void 0!==t?t:"")},time(n){t[n]=Date.now()},timeEnd(r,s){const o=t[r];if(void 0!==o){const a=Date.now()-o;if(delete t[r],e){const e=s?`${s} ${a}ms`:`${r} ${a}ms`;console.log(n,e)}return a}return 0},lifecycleInit(n,e){this.info(`初始化完成 integrateId=${n} requestDomain=${e}`)},lifecycleDestroy(n){this.info(`销毁实例 integrateId=${n}`)},lifecycleSend(n,e){this.info(`发送消息 integrateId=${n} length=${e}`),this.time(`send_${n}`)},lifecycleReply(n,e){const t=this.timeEnd(`send_${n}`,"AI 回复");this.info(`AI 回复 integrateId=${n} length=${e} duration=${t}ms`)},lifecycleError(n,e,t){this.timeEnd(`send_${n}`),this.error(`请求失败 integrateId=${n} status=${e} message=${t}`)},lifecycleClear(n){this.info(`清空会话 integrateId=${n}`)},lifecycleStreamDone(n,e){const t=this.timeEnd(`send_${n}`,"流式回复");this.info(`流式回复完成 integrateId=${n} length=${e} duration=${t}ms`)},lifecycleCategoryChange(n){this.info(`切换知识库分类 categoryId=${n}`)}};const s={"zh-CN":{title:"AI 智能助手",minimize:"最小化",close:"关闭",status_online:"在线",welcome_title:"你好,我是 AI 智能助手",welcome_desc:"有什么可以帮你的吗?在下方输入框开始提问吧~",placeholder:"输入您的问题...",send:"发送",stop:"停止生成",new_message:"新消息",copy:"复制",copied:"已复制",retry:"重新生成",retrying:"重新生成中...",loading:"正在思考...",stream_interrupted:"回复被中断",stream_unstable:"网络不稳定,内容可能不完整",category_placeholder:"选择知识库分类",category_all:"全部分类",category_load_error:"加载分类失败",source_title:"参考来源",source_count:"{n} 条参考来源",source_loading:"加载来源中...",clear:"清空对话",clear_confirm:"确定清空所有对话记录?",history_title:"历史会话",history_empty:"暂无历史会话",history_load_error:"加载会话列表失败",history_delete_confirm:"确定删除该会话?",history_export:"导出",history_delete:"删除",history_search:"搜索会话...",feedback_up:"有帮助",feedback_down:"没帮助",teaser_text:"有什么可以帮你的吗?",new_msg_announce:"收到新消息",error_network:"网络连接失败,请检查网络",error_timeout:"请求超时,请稍后重试",error_server:"服务器异常,请稍后重试",error_cors:"跨域请求被拦截,请联系管理员将当前域名加入 API 白名单",error_auth:"鉴权失败,请联系管理员",error_forbidden:"无访问权限,请联系管理员配置",error_not_found:"请求的资源不存在",error_rate_limit:"请求过于频繁,请稍后重试",error_unavailable:"服务暂不可用,请稍后重试",error_unknown:"请求发生未知错误",error_send:"发送失败,请稍后重试",error_stream_unsupported:"浏览器不支持流式读取"},en:{title:"AI Assistant",minimize:"Minimize",close:"Close",status_online:"Online",welcome_title:"Hi, I am your AI assistant",welcome_desc:"How can I help you? Type your question below to get started.",placeholder:"Type your question...",send:"Send",stop:"Stop generating",new_message:"New message",copy:"Copy",copied:"Copied",retry:"Regenerate",retrying:"Regenerating...",loading:"Thinking...",stream_interrupted:"Response interrupted",stream_unstable:"Network unstable, content may be incomplete",category_placeholder:"Select category",category_all:"All categories",category_load_error:"Failed to load categories",source_title:"Sources",source_count:"{n} source(s)",source_loading:"Loading sources...",clear:"Clear chat",clear_confirm:"Clear all conversation history?",history_title:"History",history_empty:"No conversations yet",history_load_error:"Failed to load conversations",history_delete_confirm:"Delete this conversation?",history_export:"Export",history_delete:"Delete",history_search:"Search conversations...",feedback_up:"Helpful",feedback_down:"Not helpful",teaser_text:"How can I help you?",new_msg_announce:"New message received",error_network:"Network connection failed",error_timeout:"Request timed out, please try again",error_server:"Server error, please try again later",error_cors:"CORS request blocked. Please contact admin to whitelist your domain",error_auth:"Authentication failed, please contact admin",error_forbidden:"Access denied, please contact admin",error_not_found:"Resource not found",error_rate_limit:"Too many requests, please try again later",error_unavailable:"Service temporarily unavailable",error_unknown:"Unknown request error",error_send:"Failed to send, please try again",error_stream_unsupported:"Browser does not support streaming"}};let o="zh-CN";function a(n,e){let t=(s[o]||s["zh-CN"])[n]||s["zh-CN"][n]||n;if(e)for(const[n,r]of Object.entries(e))t=t.replace(`{${n}}`,String(r));return t}let i=null;function c(n){i&&(i.chatId=n)}function l(){return(null==i?void 0:i.chatId)||""}function d(n){if(!i)throw new Error("API 配置未初始化");return`${i.requestDomain.replace(/\/+$/,"")}${n.startsWith("/")?n:`/${n}`}`}function p(n,e,t){null!=t&&("string"==typeof t&&""===t.trim()||n.set(e,String(t)))}async function u(n,e={},t=3e4,r){const s=new AbortController,o=setTimeout(()=>s.abort(),t);r&&(r.aborted?s.abort():r.addEventListener("abort",()=>s.abort(),{once:!0}));try{return await fetch(n,Object.assign(Object.assign({},e),{signal:s.signal,mode:"cors",credentials:"include"}))}catch(n){if(null==r?void 0:r.aborted)throw new k("aborted","aborted");if(n instanceof DOMException&&"AbortError"===n.name)throw new k(a("error_timeout"),"timeout");if(n instanceof TypeError&&n.message.includes("Failed to fetch"))throw new k(a("error_cors"),"cors");throw new k(a("error_network"),"network")}finally{clearTimeout(o)}}class k extends Error{constructor(n,e){super(n),this.name="CskError",this.type=e}}function m(n){switch(n){case 401:return a("error_auth");case 403:return a("error_forbidden");case 404:return a("error_not_found");case 429:return a("error_rate_limit");case 500:return a("error_server");case 502:case 503:return a("error_unavailable");default:return`${a("error_unknown")}(${n})`}}async function g(n){const e=function(n){const e=new URLSearchParams;return e.set("message",n),e.set("chatId",i.chatId),p(e,"roleId",i.integrateId),p(e,"accountId",i.userId),d(`/ai/assistant_app/chat/sync?${e.toString()}`)}(n);r.lifecycleSend(i.integrateId,n.length);try{const n=await u(e);if(!n.ok){const e=m(n.status);throw r.lifecycleError(i.integrateId,String(n.status),e),new k(e,`http_${n.status}`)}const t=await n.text();return r.lifecycleReply(i.integrateId,t.length),t}catch(n){if(n instanceof k)throw n;throw r.lifecycleError(i.integrateId,"unknown",String(n)),new k(a("error_unknown"),"unknown")}}async function h(n,e,t,s,o,c,l){var g;const h=c?function(n,e){const t=new URLSearchParams;return t.set("message",n),t.set("chatId",i.chatId),t.set("rewriteStrategy","REWRITE"),p(t,"roleId",i.integrateId),p(t,"accountId",i.userId),p(t,"categoryId",null!=e?e:i.categoryId),d(`/ai/assistant_app/chat/rag/sse?${t.toString()}`)}(n,o):function(n,e){const t=new URLSearchParams;return t.set("message",n),t.set("chatId",i.chatId),p(t,"roleId",i.integrateId),p(t,"accountId",i.userId),p(t,"categoryId",null!=e?e:i.categoryId),d(`/ai/assistant_app/chat/sse?${t.toString()}`)}(n,o);let b="";r.lifecycleSend(i.integrateId,n.length);try{const n=await u(h,{},6e4,l);if(!n.ok){const e=m(n.status);return r.lifecycleError(i.integrateId,String(n.status),e),void s(new k(e,`http_${n.status}`))}const o=null===(g=n.body)||void 0===g?void 0:g.getReader();if(!o)return void s(new k(a("error_stream_unsupported"),"stream_unsupported"));const c=new TextDecoder("utf-8",{stream:!0});let d="";try{for(;;){const{done:n,value:t}=await o.read();if(n)break;d+=c.decode(t,{stream:!0});const r=d.split("\n");d=r.pop()||"";for(const n of r){const t=n.trim();if(t&&!t.startsWith(":"))if(t.startsWith("data:")){const n=t.substring(5).trim();n&&(b+=n,e(n))}else{if("[DONE]"===t)break;t.startsWith("event:")||t.startsWith("id:")||t.startsWith("retry:")||(b+=t,e(t))}}}if(d.trim()){const n=d.trim();if(n.startsWith("data:")){const t=n.substring(5).trim();t&&(b+=t,e(t))}else"[DONE]"!==n&&(b+=n,e(n))}}catch(n){if(null==l?void 0:l.aborted)r.info(`流式被用户中断,保留已生成内容 length=${b.length}`);else{if(!(b.length>0))throw n;e("\n\n"+a("stream_unstable"))}}finally{o.releaseLock()}r.lifecycleStreamDone(i.integrateId,b.length),t()}catch(n){if((null==l?void 0:l.aborted)||n instanceof k&&"aborted"===n.type)return void t();n instanceof k?s(n):(r.lifecycleError(i.integrateId,"unknown",String(n)),s(new k(a("error_network"),"network")))}}async function b(n,e){const t=function(n,e){const t=new URLSearchParams;return t.set("message",n),t.set("chatId",i.chatId),t.set("rewriteStrategy","REWRITE"),p(t,"roleId",i.integrateId),p(t,"accountId",i.userId),p(t,"categoryId",null!=e?e:i.categoryId),d(`/ai/assistant_app/rag/sources?${t.toString()}`)}(n,e);try{const n=await u(t);if(!n.ok)throw new k(m(n.status),`http_${n.status}`);const e=await n.json();return e.success&&Array.isArray(e.data)?(r.info(`获取引用来源 count=${e.data.length}`),e.data):[]}catch(n){return r.error("获取引用来源失败",n),[]}}async function f(n=1,e=20,t,s){let o=`/conversation/list?page=${n}&size=${e}`;t&&(o+=`&accountId=${encodeURIComponent(t)}`),s&&(o+=`&roleId=${encodeURIComponent(s)}`);const a=d(o);try{const n=await u(a);if(!n.ok)throw new k(m(n.status),`http_${n.status}`);const e=await n.json();return{list:e.success&&Array.isArray(e.data)?e.data:[],total:e.total||0,pages:e.pages||0}}catch(n){return r.error("加载会话列表失败",n),{list:[],total:0,pages:0}}}async function y(n){const e=d(`/conversation/${n}/messages`);try{const n=await u(e);if(!n.ok)throw new k(m(n.status),`http_${n.status}`);const t=await n.json();return{messages:t.success&&Array.isArray(t.data)?t.data:[],total:t.total||0}}catch(n){return r.error("加载会话消息失败",n),{messages:[],total:0}}}async function x(n){const e=d(`/conversation/${n}`);try{const t=await u(e,{method:"DELETE"});if(!t.ok)throw new k(m(t.status),`http_${t.status}`);const s=await t.json();return r.info(`删除会话 id=${n} success=${s.success}`),s.success||!1}catch(n){return r.error("删除会话失败",n),!1}}function v(n){return d(`/conversation/${n}/export`)}async function w(){if(!i)return"";const n=function(n,e){try{return localStorage.getItem(_(n,e))||""}catch(n){return""}}(i.integrateId,i.userId);if(n)return i.chatId=n,r.info(`从缓存恢复 chatId=${n}`),n;try{const n=await f(1,5,i.userId,i.integrateId);if(n.list.length>0){const e=n.list[0],t=e.conversationId||e.chatId||"";if(t)return i.chatId=t,E(i.integrateId,i.userId,t),r.info(`从后端恢复会话 chatId=${t} messageCount=${e.messageCount}`),t}}catch(n){r.warn("查询后端会话列表失败,将生成新 chatId",n)}const e=function(){const n="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${n}`}();return i.chatId=e,E(i.integrateId,i.userId,e),r.info(`生成新 chatId=${e}`),e}function _(n,e){return`csk_chatId_${n}${e?"_"+e:""}`}function E(n,e,t){try{t?localStorage.setItem(_(n,e),t):localStorage.removeItem(_(n,e))}catch(n){}}let C=null;function I(n){const e=$(n.primaryColor,-15),t=$(n.primaryColor,18),r=function(n){const e=n.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);return e?`${parseInt(e[1],16)}, ${parseInt(e[2],16)}, ${parseInt(e[3],16)}`:"79, 70, 229"}(n.primaryColor);return`\n --csk-primary: ${n.primaryColor};\n --csk-primary-hover: ${e};\n --csk-primary-light: ${t};\n --csk-primary-rgb: ${r};\n --csk-bg-user: linear-gradient(135deg, ${n.primaryColor}, ${e});\n --csk-bg-ai: #ffffff;\n --csk-text-user: #ffffff;\n --csk-text-ai: #1F2937;\n --csk-window-width: ${n.width}px;\n --csk-radius: 16px;\n --csk-shadow-window: 0 12px 48px rgba(15, 23, 42, 0.18), 0 2px 8px rgba(15, 23, 42, 0.06);\n --csk-shadow-bubble: 0 1px 2px rgba(15, 23, 42, 0.06);\n --csk-border: #ECEEF2;\n --csk-bg-app: #F6F7F9;\n `}function $(n,e){const t=n.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(!t)return n;const r=n=>Math.max(0,Math.min(255,n)),s=r(parseInt(t[1],16)+e),o=r(parseInt(t[2],16)+e),a=r(parseInt(t[3],16)+e);return`#${s.toString(16).padStart(2,"0")}${o.toString(16).padStart(2,"0")}${a.toString(16).padStart(2,"0")}`}function A(n){document.querySelector("style[data-csk-sdk]")||(C=document.createElement("style"),C.setAttribute("data-csk-sdk",""),C.textContent=function(n){return`\n/* ChatbotSDK 样式 - csk- 命名空间 */\n.csk-root {\n ${I(n)}\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif;\n font-size: 14px;\n line-height: 1.55;\n color: #1F2937;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n box-sizing: border-box;\n}\n.csk-root *, .csk-root *::before, .csk-root *::after { box-sizing: border-box; }\n\n/* ========== 悬浮按钮 ========== */\n.csk-launcher {\n position: fixed;\n bottom: 24px;\n z-index: 9998;\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: #fff;\n user-select: none;\n overflow: visible;\n /* 半透明白色光环边框,在白色页面上清晰分离按钮与背景 */\n border: 2.5px solid rgba(255, 255, 255, 0.55);\n /* 三层投影:接地阴影 + 彩色光晕,把按钮从白底「托」出来 */\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.25s ease,\n border-color 0.25s ease;\n animation: csk-launcher-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;\n}\n.csk-launcher--right { right: 24px; }\n.csk-launcher--left { left: 24px; }\n\n/* 高光扫过动效 */\n.csk-launcher::before {\n content: '';\n position: absolute;\n top: -50%;\n left: -50%;\n width: 40%;\n height: 200%;\n border-radius: 50%;\n background: linear-gradient(\n 105deg,\n transparent 30%,\n rgba(255, 255, 255, 0.28) 48%,\n rgba(255, 255, 255, 0.1) 52%,\n transparent 70%\n );\n transform: rotate(25deg);\n animation: csk-shimmer 4s ease-in-out infinite;\n pointer-events: none;\n}\n/* 呼吸色晕 — 配合接地阴影,强化白底上的立体存在感 */\n.csk-launcher::after {\n content: '';\n position: absolute;\n inset: -18px;\n border-radius: 50%;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.18) 0%, rgba(var(--csk-primary-rgb), 0.05) 45%, transparent 68%);\n animation: csk-breathe 3.5s ease-in-out infinite;\n pointer-events: none;\n}\n.csk-launcher:hover {\n transform: translateY(-3px) scale(1.08);\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 2px 6px rgba(0, 0, 0, 0.10),\n 0 8px 24px rgba(0, 0, 0, 0.14),\n 0 10px 36px rgba(var(--csk-primary-rgb), 0.32),\n 0 0 56px rgba(var(--csk-primary-rgb), 0.14);\n}\n.csk-launcher:hover::before { animation-play-state: paused; }\n.csk-launcher:hover::after {\n animation: none;\n inset: -22px;\n background: radial-gradient(circle, rgba(var(--csk-primary-rgb), 0.22) 0%, rgba(var(--csk-primary-rgb), 0.06) 45%, transparent 68%);\n}\n.csk-launcher:active { transform: scale(0.93); }\n.csk-launcher svg {\n width: 30px;\n height: 30px;\n position: relative;\n z-index: 1;\n filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.15));\n}\n\n@keyframes csk-launcher-in {\n 0% { opacity: 0; transform: scale(0.5) translateY(16px); }\n 60% { transform: scale(1.06) translateY(-2px); }\n 100% { opacity: 1; transform: scale(1) translateY(0); }\n}\n@keyframes csk-shimmer {\n 0%, 100% { left: -60%; opacity: 0; }\n 20% { opacity: 1; }\n 60% { opacity: 1; }\n 80% { left: 120%; opacity: 0; }\n}\n@keyframes csk-breathe {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.15); opacity: 0.35; }\n}\n\n/* SVG 图标内部动效:眨眼 */\n.csk-launcher .csk-ico-eye {\n animation: csk-eye-blink 4s ease-in-out infinite;\n}\n@keyframes csk-eye-blink {\n 0%, 42%, 48%, 100% { opacity: 1; }\n 45% { opacity: 0.1; }\n}\n/* SVG 图标内部动效:天线能量闪烁 */\n.csk-launcher .csk-ico-antenna {\n animation: csk-antenna-glow 2s ease-in-out infinite;\n}\n@keyframes csk-antenna-glow {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n/* ========== 聊天弹窗 ========== */\n.csk-window {\n position: fixed;\n bottom: 24px;\n z-index: 9999;\n width: var(--csk-window-width);\n height: 600px;\n max-height: calc(100vh - 48px);\n background: #fff;\n border-radius: var(--csk-radius);\n box-shadow: var(--csk-shadow-window);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n transform-origin: bottom right;\n transition: opacity 0.24s ease, transform 0.24s cubic-bezier(0.34, 1.2, 0.64, 1), visibility 0.24s;\n opacity: 1;\n transform: translateY(0) scale(1);\n visibility: visible;\n pointer-events: auto;\n}\n.csk-window--right { right: 24px; transform-origin: bottom right; }\n.csk-window--left { left: 24px; transform-origin: bottom left; }\n.csk-window--hidden {\n opacity: 0;\n transform: translateY(12px) scale(0.96);\n visibility: hidden;\n pointer-events: none;\n}\n\n/* ========== 头部 ========== */\n.csk-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n min-height: 60px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: move;\n user-select: none;\n position: relative;\n flex-shrink: 0;\n}\n.csk-header::after {\n content: '';\n position: absolute;\n left: 0; right: 0; bottom: 0;\n height: 24px;\n background: linear-gradient(to bottom, rgba(0,0,0,0.04), transparent);\n pointer-events: none;\n}\n.csk-header__left {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n}\n.csk-header__avatar {\n width: 38px;\n height: 38px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.22);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);\n}\n.csk-header__avatar svg { width: 22px; height: 22px; }\n.csk-header__info {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n.csk-header__title {\n font-size: 15px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n letter-spacing: 0.2px;\n}\n.csk-header__status {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-size: 11.5px;\n opacity: 0.9;\n margin-top: 2px;\n}\n.csk-status-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #6EE7B7;\n box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7);\n animation: csk-status-pulse 2s infinite;\n}\n@keyframes csk-status-pulse {\n 0% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0.7); }\n 70% { box-shadow: 0 0 0 6px rgba(110, 231, 183, 0); }\n 100% { box-shadow: 0 0 0 0 rgba(110, 231, 183, 0); }\n}\n.csk-header__actions {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n.csk-header__btn,\n.csk-history-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: none;\n background: transparent;\n color: #fff;\n cursor: pointer;\n border-radius: 8px;\n transition: background 0.15s, transform 0.15s;\n}\n.csk-header__btn:hover,\n.csk-history-btn:hover {\n background: rgba(255, 255, 255, 0.2);\n}\n.csk-header__btn:active,\n.csk-history-btn:active { transform: scale(0.92); }\n\n/* ========== 消息区 ========== */\n.csk-messages {\n flex: 1;\n overflow-y: auto;\n padding: 20px 16px 12px;\n background: var(--csk-bg-app);\n scroll-behavior: smooth;\n}\n.csk-messages::-webkit-scrollbar { width: 6px; }\n.csk-messages::-webkit-scrollbar-track { background: transparent; }\n.csk-messages::-webkit-scrollbar-thumb {\n background: #D8DCE3;\n border-radius: 3px;\n}\n.csk-messages::-webkit-scrollbar-thumb:hover { background: #C2C7D0; }\n\n/* 欢迎空状态 */\n.csk-welcome {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 48px 24px 32px;\n color: #6B7280;\n animation: csk-fade-in 0.3s ease;\n}\n.csk-welcome__avatar {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--csk-bg-user);\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 14px;\n box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-welcome__avatar svg { width: 30px; height: 30px; }\n.csk-welcome__title {\n font-size: 15px;\n font-weight: 600;\n color: #1F2937;\n margin-bottom: 4px;\n}\n.csk-welcome__desc {\n font-size: 13px;\n color: #9CA3AF;\n line-height: 1.6;\n}\n\n/* 消息气泡 */\n.csk-msg {\n display: flex;\n margin-bottom: 18px;\n max-width: 100%;\n word-break: break-word;\n animation: csk-msg-in 0.28s cubic-bezier(0.22, 1, 0.36, 1);\n}\n.csk-msg--user {\n flex-direction: row-reverse;\n align-items: flex-end;\n}\n.csk-msg--ai {\n flex-direction: row;\n align-items: flex-start;\n}\n.csk-msg__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg__avatar svg { width: 18px; height: 18px; }\n.csk-msg__avatar--ai {\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n}\n.csk-msg__avatar--user {\n background: var(--csk-bg-user);\n color: #fff;\n}\n.csk-msg__content {\n display: flex;\n flex-direction: column;\n min-width: 0;\n max-width: calc(100% - 46px);\n}\n.csk-msg--user .csk-msg__content { align-items: flex-end; }\n.csk-msg--ai .csk-msg__content { align-items: flex-start; }\n.csk-msg__bubble {\n padding: 10px 14px;\n border-radius: 16px;\n font-size: 14px;\n line-height: 1.6;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-msg--user .csk-msg__bubble {\n background: var(--csk-bg-user);\n color: var(--csk-text-user);\n border-radius: 16px 16px 4px 16px;\n}\n.csk-msg--ai .csk-msg__bubble {\n background: var(--csk-bg-ai);\n color: var(--csk-text-ai);\n border-radius: 16px 16px 16px 4px;\n border: 1px solid var(--csk-border);\n}\n.csk-msg__time {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 5px;\n padding: 0 4px;\n}\n\n@keyframes csk-msg-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n@keyframes csk-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* ========== Loading 动画 ========== */\n.csk-loading {\n display: flex;\n align-items: center;\n margin-bottom: 18px;\n animation: csk-msg-in 0.28s ease;\n}\n.csk-loading__avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: #fff;\n color: var(--csk-primary);\n border: 1px solid var(--csk-border);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin: 0 8px;\n box-shadow: var(--csk-shadow-bubble);\n}\n.csk-loading__avatar svg { width: 18px; height: 18px; }\n.csk-loading__bubble {\n background: #fff;\n border: 1px solid var(--csk-border);\n border-radius: 16px 16px 16px 4px;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n.csk-loading__dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #B4B9C2;\n animation: csk-bounce 1.4s ease-in-out infinite both;\n}\n.csk-loading__dot:nth-child(1) { animation-delay: 0s; }\n.csk-loading__dot:nth-child(2) { animation-delay: 0.16s; }\n.csk-loading__dot:nth-child(3) { animation-delay: 0.32s; }\n\n@keyframes csk-bounce {\n 0%, 80%, 100% { transform: scale(0.6); opacity: 0.6; }\n 40% { transform: scale(1); opacity: 1; }\n}\n\n/* ========== 输入区 ========== */\n.csk-input-area {\n padding: 10px 12px 14px;\n background: #fff;\n border-top: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-input-wrap {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n background: var(--csk-bg-app);\n border: 1px solid var(--csk-border);\n border-radius: 14px;\n padding: 6px 6px 6px 14px;\n transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;\n}\n.csk-input-wrap--focus {\n border-color: var(--csk-primary);\n background: #fff;\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n.csk-input {\n flex: 1;\n border: none;\n background: transparent;\n padding: 8px 0;\n font-size: 14px;\n outline: none;\n font-family: inherit;\n resize: none;\n min-height: 22px;\n max-height: 120px;\n line-height: 1.5;\n color: #1F2937;\n}\n.csk-input::placeholder { color: #9CA3AF; }\n.csk-root .csk-input:focus-visible { outline: none; }\n.csk-send-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n min-width: 36px;\n border: none;\n border-radius: 10px;\n background: var(--csk-bg-user);\n color: #fff;\n cursor: pointer;\n transition: transform 0.18s, box-shadow 0.18s, opacity 0.18s;\n box-shadow: 0 3px 10px rgba(var(--csk-primary-rgb), 0.3);\n}\n.csk-send-btn:hover:not(:disabled) {\n transform: translateY(-1px);\n box-shadow: 0 5px 14px rgba(var(--csk-primary-rgb), 0.4);\n}\n.csk-send-btn:active:not(:disabled) { transform: scale(0.92); }\n.csk-send-btn:disabled {\n background: #D1D5DB;\n box-shadow: none;\n cursor: not-allowed;\n opacity: 0.7;\n}\n.csk-send-btn svg { width: 18px; height: 18px; }\n\n/* ========== 清空按钮 ========== */\n.csk-clear-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 999px;\n background: #fff;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n margin: 0 auto 8px;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-clear-btn:hover {\n background: #FEF2F2;\n border-color: #FCA5A5;\n color: #DC2626;\n}\n\n/* ========== P1: 知识库分类下拉 ========== */\n.csk-category-bar {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n border-top: 1px solid var(--csk-border);\n background: #FBFBFC;\n gap: 8px;\n flex-shrink: 0;\n}\n.csk-category-bar__label {\n font-size: 13px;\n white-space: nowrap;\n}\n.csk-category-select {\n flex: 1;\n padding: 6px 28px 6px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n color: #374151;\n background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 9px center;\n appearance: none;\n -webkit-appearance: none;\n outline: none;\n cursor: pointer;\n font-family: inherit;\n transition: border-color 0.2s, box-shadow 0.2s;\n max-width: 220px;\n}\n.csk-category-select:focus {\n border-color: var(--csk-primary);\n box-shadow: 0 0 0 3px rgba(var(--csk-primary-rgb), 0.12);\n}\n\n/* ========== P1: RAG 引用来源卡片 ========== */\n.csk-sources {\n margin-top: 8px;\n border: 1px solid var(--csk-border);\n border-radius: 12px;\n overflow: hidden;\n font-size: 12px;\n max-width: 100%;\n background: #FAFBFC;\n}\n.csk-sources__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: #F3F4F7;\n cursor: pointer;\n user-select: none;\n transition: background 0.15s;\n}\n.csk-sources__header:hover { background: #ECEEF2; }\n.csk-sources__title {\n display: flex;\n align-items: center;\n gap: 5px;\n font-weight: 500;\n color: #374151;\n}\n.csk-sources__arrow {\n transition: transform 0.2s;\n color: #9CA3AF;\n font-size: 10px;\n}\n.csk-sources--collapsed .csk-sources__arrow { transform: rotate(-90deg); }\n.csk-sources__body {\n border-top: 1px solid var(--csk-border);\n padding: 0;\n}\n.csk-sources--collapsed .csk-sources__body { display: none; }\n.csk-source-item {\n padding: 9px 12px;\n border-bottom: 1px solid #F0F1F4;\n transition: background 0.15s;\n}\n.csk-source-item:last-child { border-bottom: none; }\n.csk-source-item:hover { background: #fff; }\n.csk-source-item__name {\n font-weight: 500;\n color: #1F2937;\n margin-bottom: 3px;\n}\n.csk-source-item__snippet {\n color: #6B7280;\n line-height: 1.5;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n}\n.csk-source-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 4px;\n}\n\n/* ========== P1: Markdown 渲染样式 ========== */\n.csk-msg--ai .csk-msg__bubble .csk-md-p { margin: 0 0 8px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-p:last-child { margin-bottom: 0; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h1,\n.csk-msg--ai .csk-msg__bubble .csk-md-h2,\n.csk-msg--ai .csk-msg__bubble .csk-md-h3,\n.csk-msg--ai .csk-msg__bubble .csk-md-h4,\n.csk-msg--ai .csk-msg__bubble .csk-md-h5,\n.csk-msg--ai .csk-msg__bubble .csk-md-h6 {\n margin: 14px 0 6px;\n font-weight: 600;\n line-height: 1.3;\n color: #111827;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-h1 { font-size: 20px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h2 { font-size: 17px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h3 { font-size: 15px; }\n.csk-msg--ai .csk-msg__bubble .csk-md-h4 { font-size: 14px; }\n\n.csk-md-code-block {\n background: #1E293B;\n color: #E2E8F0;\n padding: 12px 14px;\n border-radius: 10px;\n overflow-x: auto;\n margin: 8px 0;\n font-size: 13px;\n line-height: 1.55;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-md-code-block code {\n background: none;\n padding: 0;\n border-radius: 0;\n font-size: inherit;\n color: inherit;\n}\n.csk-md-inline-code {\n background: rgba(var(--csk-primary-rgb), 0.1);\n color: var(--csk-primary);\n padding: 1px 6px;\n border-radius: 5px;\n font-size: 13px;\n font-family: 'SF Mono', 'Consolas', 'Menlo', 'Monaco', monospace;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol {\n padding-left: 22px;\n margin: 6px 0;\n}\n.csk-msg--ai .csk-msg__bubble .csk-md-ul li,\n.csk-msg--ai .csk-msg__bubble .csk-md-ol li { margin-bottom: 4px; }\n.csk-md-blockquote {\n border-left: 3px solid var(--csk-primary);\n padding: 2px 12px;\n margin: 8px 0;\n color: #6B7280;\n background: rgba(var(--csk-primary-rgb), 0.05);\n border-radius: 0 6px 6px 0;\n}\n.csk-md-link {\n color: var(--csk-primary);\n text-decoration: none;\n border-bottom: 1px solid rgba(var(--csk-primary-rgb), 0.3);\n transition: border-color 0.15s;\n}\n.csk-md-link:hover { border-bottom-color: var(--csk-primary); }\n.csk-md-hr {\n border: none;\n border-top: 1px solid var(--csk-border);\n margin: 12px 0;\n}\n\n/* ========== P2: 会话管理面板 ========== */\n.csk-history-panel {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: #fff;\n z-index: 10;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: csk-slide-in 0.24s ease;\n}\n.csk-history-panel--hidden { display: none; }\n@keyframes csk-slide-in {\n from { transform: translateX(100%); opacity: 0.4; }\n to { transform: translateX(0); opacity: 1; }\n}\n.csk-history-panel__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid var(--csk-border);\n background: var(--csk-bg-app);\n flex-shrink: 0;\n}\n.csk-history-panel__title {\n font-size: 14px;\n font-weight: 600;\n color: #1F2937;\n}\n.csk-history-panel__back {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 12px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n background: #fff;\n color: #374151;\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n.csk-history-panel__back:hover { background: #F3F4F6; }\n.csk-history-panel__list {\n flex: 1;\n overflow-y: auto;\n padding: 10px;\n}\n.csk-history-panel__list::-webkit-scrollbar { width: 5px; }\n.csk-history-panel__list::-webkit-scrollbar-thumb { background: #E5E7EB; border-radius: 2px; }\n.csk-history-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 11px 12px;\n border-radius: 10px;\n cursor: pointer;\n transition: background 0.15s;\n margin-bottom: 5px;\n border: 1px solid transparent;\n}\n.csk-history-item:hover { background: #F3F4F6; }\n.csk-history-item--active {\n background: rgba(var(--csk-primary-rgb), 0.08);\n border-color: rgba(var(--csk-primary-rgb), 0.2);\n}\n.csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.12); }\n.csk-history-item__info { flex: 1; min-width: 0; }\n.csk-history-item__id {\n font-size: 13px;\n font-weight: 500;\n color: #1F2937;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.csk-history-item__meta {\n font-size: 11px;\n color: #9CA3AF;\n margin-top: 3px;\n}\n.csk-history-item__actions {\n display: flex;\n gap: 4px;\n margin-left: 8px;\n opacity: 0;\n transition: opacity 0.15s;\n}\n.csk-history-item:hover .csk-history-item__actions { opacity: 1; }\n.csk-history-action {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 7px;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.15s;\n}\n.csk-history-action--export { background: #EFF6FF; color: #2563EB; }\n.csk-history-action--export:hover { background: #DBEAFE; }\n.csk-history-action--delete { background: #FEF2F2; color: #DC2626; }\n.csk-history-action--delete:hover { background: #FEE2E2; }\n.csk-history-panel__empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 20px;\n color: #9CA3AF;\n font-size: 13px;\n text-align: center;\n}\n.csk-history-panel__empty-icon {\n font-size: 34px;\n margin-bottom: 10px;\n opacity: 0.5;\n}\n.csk-history-panel__loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n color: #9CA3AF;\n font-size: 13px;\n}\n.csk-history-panel__loadmore {\n display: block;\n width: 100%;\n padding: 10px;\n border: none;\n background: #F9FAFB;\n color: #6B7280;\n font-size: 12px;\n cursor: pointer;\n text-align: center;\n transition: background 0.15s;\n}\n.csk-history-panel__loadmore:hover { background: #F3F4F6; }\n\n/* ========== 快捷问题芯片 ========== */\n.csk-quick-replies {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n margin-top: 18px;\n max-width: 320px;\n}\n.csk-quick-reply {\n border: 1px solid var(--csk-border);\n background: #fff;\n color: #374151;\n font-size: 12.5px;\n padding: 7px 13px;\n border-radius: 999px;\n cursor: pointer;\n font-family: inherit;\n line-height: 1.3;\n transition: all 0.18s ease;\n max-width: 100%;\n}\n.csk-quick-reply:hover {\n border-color: var(--csk-primary);\n color: var(--csk-primary);\n background: rgba(var(--csk-primary-rgb), 0.06);\n transform: translateY(-1px);\n}\n.csk-quick-reply:active { transform: scale(0.96); }\n\n/* ========== AI 消息操作条 ========== */\n.csk-msg__actions {\n display: flex;\n gap: 2px;\n margin-top: 5px;\n padding: 0 2px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n.csk-msg--ai:hover .csk-msg__actions { opacity: 1; }\n.csk-msg--streaming .csk-msg__actions { display: none; }\n.csk-action-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: transparent;\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.csk-action-btn:hover {\n background: #F3F4F6;\n color: #374151;\n}\n.csk-action-btn--done { color: #10B981; }\n.csk-action-btn:active { transform: scale(0.9); }\n\n/* ========== 流式打字光标 ========== */\n.csk-caret {\n display: inline-block;\n width: 7px;\n height: 15px;\n margin-left: 2px;\n vertical-align: text-bottom;\n background: var(--csk-primary);\n border-radius: 1px;\n animation: csk-caret-blink 1s step-end infinite;\n}\n@keyframes csk-caret-blink {\n 0%, 50% { opacity: 1; }\n 51%, 100% { opacity: 0; }\n}\n\n/* ========== 代码块复制按钮 ========== */\n.csk-md-code-block { position: relative; }\n.csk-md-code-copy {\n position: absolute;\n top: 8px;\n right: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(255, 255, 255, 0.12);\n color: #CBD5E1;\n border-radius: 6px;\n cursor: pointer;\n opacity: 0;\n transition: all 0.15s ease;\n}\n.csk-md-code-block:hover .csk-md-code-copy { opacity: 1; }\n.csk-md-code-copy:hover { background: rgba(255, 255, 255, 0.22); color: #fff; }\n.csk-md-code-copy:active { transform: scale(0.9); }\n\n/* ========== 新消息提示按钮 ========== */\n.csk-newmsg {\n position: absolute;\n bottom: 82px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 5;\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 7px 14px;\n border: none;\n background: var(--csk-primary);\n color: #fff;\n font-size: 12px;\n font-family: inherit;\n border-radius: 999px;\n cursor: pointer;\n box-shadow: 0 4px 14px rgba(var(--csk-primary-rgb), 0.38);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n animation: csk-msg-in 0.25s ease;\n white-space: nowrap;\n}\n.csk-newmsg:hover { transform: translateX(-50%) translateY(-1px); box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.48); }\n.csk-newmsg:active { transform: translateX(-50%) scale(0.95); }\n.csk-newmsg--hidden { display: none; }\n\n/* ========== 发送按钮停止态 ========== */\n.csk-send-btn--stop {\n background: #EF4444 !important;\n box-shadow: 0 3px 10px rgba(239, 68, 68, 0.35) !important;\n}\n.csk-send-btn--stop:hover:not(:disabled) {\n box-shadow: 0 5px 14px rgba(239, 68, 68, 0.45) !important;\n}\n\n/* ========== 暗色模式 ========== */\n.csk-root.csk-dark {\n --csk-bg-ai: #1E1E2E;\n --csk-text-ai: #E2E8F0;\n --csk-border: #3B3B52;\n --csk-bg-app: #141421;\n color: #E2E8F0;\n}\n.csk-dark .csk-window {\n background: #1A1A2E;\n box-shadow: 0 12px 48px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.2);\n}\n.csk-dark .csk-header::after { background: linear-gradient(to bottom, rgba(0,0,0,0.12), transparent); }\n.csk-dark .csk-msg__avatar--ai {\n background: var(--csk-bg-ai);\n color: var(--csk-primary);\n border-color: var(--csk-border);\n}\n.csk-dark .csk-input-area { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-input-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-input-wrap--focus { background: #1A1A2E; border-color: var(--csk-primary); }\n.csk-dark .csk-input { color: #E2E8F0; }\n.csk-dark .csk-loading__avatar { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__bubble { background: var(--csk-bg-ai); border-color: var(--csk-border); }\n.csk-dark .csk-loading__dot { background: #6B7280; }\n.csk-dark .csk-category-bar { background: #1A1A2E; border-top-color: var(--csk-border); }\n.csk-dark .csk-category-select { background-color: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-sources { background: #1E1E2E; border-color: var(--csk-border); }\n.csk-dark .csk-sources__header { background: #25253A; }\n.csk-dark .csk-sources__header:hover { background: #2D2D48; }\n.csk-dark .csk-source-item:hover { background: var(--csk-bg-ai); }\n.csk-dark .csk-source-item__name { color: #E2E8F0; }\n.csk-dark .csk-source-item__meta { color: #6B7280; }\n.csk-dark .csk-history-panel { background: #1A1A2E; }\n.csk-dark .csk-history-panel__header { background: var(--csk-bg-app); border-bottom-color: var(--csk-border); }\n.csk-dark .csk-history-panel__back { background: var(--csk-bg-app); border-color: var(--csk-border); color: #E2E8F0; }\n.csk-dark .csk-history-panel__back:hover { background: #2D2D48; }\n.csk-dark .csk-history-item:hover { background: #25253A; }\n.csk-dark .csk-history-item__id { color: #E2E8F0; }\n.csk-dark .csk-history-item__meta { color: #6B7280; }\n.csk-dark .csk-history-item--active { background: rgba(var(--csk-primary-rgb), 0.15); }\n.csk-dark .csk-history-item--active:hover { background: rgba(var(--csk-primary-rgb), 0.22); }\n.csk-dark .csk-action-btn:hover { background: #2D2D48; color: #E2E8F0; }\n.csk-dark .csk-clear-btn { background: var(--csk-bg-app); border-color: var(--csk-border); color: #9CA3AF; }\n.csk-dark .csk-clear-btn:hover { background: #3B1A1A; border-color: #7F1D1D; color: #FCA5A5; }\n.csk-dark .csk-md-code-block { background: #0F0F1A; }\n.csk-dark .csk-md-blockquote { background: rgba(var(--csk-primary-rgb), 0.08); }\n.csk-dark .csk-md-link { color: var(--csk-primary-light); }\n.csk-dark .csk-msg--ai .csk-msg__bubble { background: var(--csk-bg-ai); color: var(--csk-text-ai); border-color: var(--csk-border); }\n.csk-dark .csk-welcome__title { color: #E2E8F0; }\n.csk-dark .csk-welcome__desc { color: #6B7280; }\n.csk-dark .csk-quick-reply { background: var(--csk-bg-app); border-color: var(--csk-border); color: #CBD5E1; }\n.csk-dark .csk-quick-reply:hover { background: rgba(var(--csk-primary-rgb), 0.12); border-color: var(--csk-primary); color: var(--csk-primary-light); }\n.csk-dark .csk-teaser { background: #2D2D48; color: #E2E8F0; box-shadow: 0 4px 20px rgba(0,0,0,0.35); }\n.csk-dark .csk-teaser::after { border-top-color: #2D2D48; }\n.csk-dark .csk-teaser__close { color: #6B7280; }\n.csk-dark .csk-teaser__close:hover { color: #9CA3AF; }\n.csk-dark .csk-feedback-btn { background: rgba(var(--csk-primary-rgb), 0.1); color: #9CA3AF; }\n.csk-dark .csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.2); color: var(--csk-primary-light); }\n.csk-dark .csk-feedback-btn--active { background: rgba(var(--csk-primary-rgb), 0.28); color: var(--csk-primary-light); }\n.csk-dark .csk-history-panel__search-wrap { background: var(--csk-bg-app); border-color: var(--csk-border); }\n.csk-dark .csk-history-panel__search-wrap:focus-within { border-color: var(--csk-primary); }\n.csk-dark .csk-history-panel__search { color: #E2E8F0; }\n.csk-dark .csk-launcher__badge { box-shadow: 0 0 0 2px #1A1A2E; }\n.csk-dark .csk-welcome__avatar { box-shadow: 0 6px 18px rgba(var(--csk-primary-rgb), 0.25); }\n.csk-dark .csk-header__avatar { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.1); }\n\n/* ========== Launcher 未读徽章 ========== */\n.csk-launcher__badge {\n position: absolute;\n top: -2px;\n right: -2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #EF4444;\n border: 2px solid #fff;\n box-shadow: 0 0 0 2px #fff;\n animation: csk-badge-in 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);\n pointer-events: none;\n}\n.csk-launcher__badge--hidden { display: none; }\n@keyframes csk-badge-in {\n from { transform: scale(0); }\n to { transform: scale(1); }\n}\n\n/* ========== Launcher 提示气泡 ========== */\n.csk-teaser {\n position: fixed;\n bottom: 90px;\n z-index: 9997;\n max-width: 240px;\n padding: 10px 14px;\n background: #fff;\n color: #1F2937;\n font-size: 13px;\n line-height: 1.5;\n border-radius: 12px;\n box-shadow: 0 4px 20px rgba(15, 23, 42, 0.15);\n animation: csk-teaser-in 0.35s cubic-bezier(0.22, 1, 0.36, 1);\n cursor: pointer;\n user-select: none;\n}\n.csk-teaser--right { right: 24px; }\n.csk-teaser--left { left: 24px; }\n.csk-teaser::after {\n content: '';\n position: absolute;\n bottom: -6px;\n right: 28px;\n width: 12px;\n height: 12px;\n background: inherit;\n border-radius: 2px;\n transform: rotate(45deg);\n box-shadow: 2px 2px 4px rgba(15, 23, 42, 0.08);\n}\n.csk-teaser--left::after { right: auto; left: 28px; }\n.csk-teaser__close {\n position: absolute;\n top: 4px;\n right: 6px;\n background: none;\n border: none;\n font-size: 16px;\n color: #9CA3AF;\n cursor: pointer;\n padding: 2px 4px;\n line-height: 1;\n border-radius: 4px;\n}\n.csk-teaser__close:hover { color: #374151; }\n.csk-teaser--hidden { display: none; }\n@keyframes csk-teaser-in {\n from { opacity: 0; transform: translateY(8px) scale(0.95); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n/* ========== 消息反馈按钮(👍 / 👎) ========== */\n.csk-feedback-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: none;\n background: rgba(var(--csk-primary-rgb), 0.08);\n color: #9CA3AF;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n padding: 0;\n}\n.csk-feedback-btn:hover { background: rgba(var(--csk-primary-rgb), 0.18); color: var(--csk-primary); }\n.csk-feedback-btn--active {\n background: rgba(var(--csk-primary-rgb), 0.28);\n color: var(--csk-primary);\n}\n.csk-feedback-btn--active.down { background: #FEF2F2; color: #EF4444; }\n.csk-feedback-btn:active { transform: scale(0.9); }\n.csk-msg--streaming .csk-feedback-btn { display: none; }\n\n/* ========== 历史会话搜索框 ========== */\n.csk-history-panel__search-wrap {\n padding: 8px 10px;\n border-bottom: 1px solid var(--csk-border);\n flex-shrink: 0;\n}\n.csk-history-panel__search-wrap:focus-within {\n border-bottom-color: var(--csk-primary);\n}\n.csk-history-panel__search {\n width: 100%;\n padding: 7px 10px;\n border: 1px solid var(--csk-border);\n border-radius: 8px;\n font-size: 12.5px;\n font-family: inherit;\n color: #1F2937;\n background: var(--csk-bg-app);\n outline: none;\n transition: border-color 0.2s;\n}\n.csk-history-panel__search:focus { border-color: var(--csk-primary); }\n.csk-history-panel__search::placeholder { color: #9CA3AF; }\n\n/* ========== a11y 焦点指示 ========== */\n.csk-root :focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n}\n.csk-root button:focus-visible {\n outline: 2px solid var(--csk-primary);\n outline-offset: 2px;\n border-radius: inherit;\n}\n/* 弹窗打开时隐藏 launcher 上的焦点环 */\n.csk-launcher:focus-visible {\n outline: none;\n border-color: rgba(255, 255, 255, 0.75);\n box-shadow:\n 0 1px 2px rgba(0, 0, 0, 0.06),\n 0 4px 16px rgba(0, 0, 0, 0.10),\n 0 6px 24px rgba(var(--csk-primary-rgb), 0.28),\n 0 0 48px rgba(var(--csk-primary-rgb), 0.12),\n 0 0 0 4px rgba(var(--csk-primary-rgb), 0.3);\n}\n\n/* ========== a11y aria-live 播报区(视觉隐藏) ========== */\n.csk-sr-only {\n position: absolute !important;\n width: 1px !important;\n height: 1px !important;\n padding: 0 !important;\n margin: -1px !important;\n overflow: hidden !important;\n clip: rect(0,0,0,0) !important;\n white-space: nowrap !important;\n border: 0 !important;\n}\n\n/* ========== 移动端适配 ========== */\n@media (max-width: 480px) {\n .csk-window {\n width: 100vw !important;\n height: 100vh !important;\n max-height: 100vh;\n bottom: 0 !important;\n right: 0 !important;\n left: 0 !important;\n border-radius: 0;\n }\n .csk-window--hidden { transform: translateY(100%); }\n .csk-launcher { bottom: 20px; }\n .csk-launcher--right { right: 20px; }\n .csk-launcher--left { left: 20px; }\n}\n`}(n),document.head.appendChild(C))}function L(){return"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,n=>{const e=16*Math.random()|0;return("x"===n?e:3&e|8).toString(16)})}function S(n){const e={"&":"&","<":"<",">":">",'"':""","'":"'"};return n.replace(/[&<>"']/g,n=>e[n]||n)}function F(){return Date.now()}const N='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8"/><rect width="12" height="8" x="6" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M9 14v2"/><path d="M15 14v2"/><path d="M18 13v3a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4v-3"/></svg>';function M(n,e){const t=document.createElement("div");t.id="csk-launcher",t.className="csk-launcher csk-launcher--"+("left-bottom"===n.position?"left":"right"),t.setAttribute("title",n.title),t.setAttribute("aria-label",n.title),t.setAttribute("role","button"),t.setAttribute("tabindex","0"),t.innerHTML=n.launcherIcon;const r=document.createElement("div");r.className="csk-launcher__badge csk-launcher__badge--hidden",t.appendChild(r);const s=function(n,e){let t=null;return function(...r){null!==t&&clearTimeout(t),t=setTimeout(()=>{n.apply(this,r),t=null},e)}}(e,300);return t.addEventListener("click",s),t.addEventListener("keydown",n=>{"Enter"!==n.key&&" "!==n.key||(n.preventDefault(),s())}),t}function D(n,e,t){const r=document.createElement("div");r.className="csk-msg csk-msg--user";const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--user",s.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>';const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.textContent=e;const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=W(t),o.appendChild(a),o.appendChild(i),r.appendChild(s),r.appendChild(o),n.appendChild(r),r}function T(n,e,t,r,s){const o=document.createElement("div");o.className="csk-msg csk-msg--ai",s&&(o.dataset.cskMsgId=s);const a=document.createElement("div");a.className="csk-msg__avatar csk-msg__avatar--ai",a.innerHTML=N;const i=document.createElement("div");i.className="csk-msg__content";const c=document.createElement("div");c.className="csk-msg__bubble",r?c.innerHTML=r(e):c.textContent=e;const l=document.createElement("div");return l.className="csk-msg__time",l.textContent=W(t),i.appendChild(c),i.appendChild(B(c,o)),i.appendChild(l),o.appendChild(a),o.appendChild(i),n.appendChild(o),P(c),o}const q='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>',z='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>';function B(n,e){const t=document.createElement("div");t.className="csk-msg__actions";const r=document.createElement("button");r.type="button",r.className="csk-action-btn",r.setAttribute("title",a("copy")),r.setAttribute("aria-label",a("copy")),r.innerHTML=q,r.addEventListener("click",async e=>{e.stopPropagation();const t=n.textContent||"";await j(t,r)});const s=document.createElement("button");s.type="button",s.className="csk-action-btn",s.setAttribute("title",a("retry")),s.setAttribute("aria-label",a("retry")),s.innerHTML=z,s.addEventListener("click",n=>{n.stopPropagation();const t=e.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:retry",{detail:{msgId:e.dataset.cskMsgId||""}}))});const o=document.createElement("button");o.type="button",o.className="csk-feedback-btn",o.setAttribute("title",a("feedback_up")),o.setAttribute("aria-label",a("feedback_up")),o.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"/></svg>',o.addEventListener("click",n=>{n.stopPropagation();const t=e.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:e.dataset.cskMsgId||"",value:"up"}}))});const i=document.createElement("button");return i.type="button",i.className="csk-feedback-btn",i.setAttribute("title",a("feedback_down")),i.setAttribute("aria-label",a("feedback_down")),i.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"/></svg>',i.addEventListener("click",n=>{n.stopPropagation();const t=e.closest(".csk-window");t&&t.dispatchEvent(new CustomEvent("csk:feedback",{detail:{msgId:e.dataset.cskMsgId||"",value:"down"}}))}),t.appendChild(r),t.appendChild(s),t.appendChild(o),t.appendChild(i),t}function H(n,e){const t=n.querySelectorAll(".csk-feedback-btn");t.length<2||(t.forEach(n=>n.classList.remove("csk-feedback-btn--active","down")),"up"===e&&t[0]&&t[0].classList.add("csk-feedback-btn--active"),"down"===e&&t[1]&&t[1].classList.add("csk-feedback-btn--active","down"))}async function j(n,e){const t=e.innerHTML;try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(n);else{const e=document.createElement("textarea");e.value=n,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)}e.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',e.classList.add("csk-action-btn--done"),setTimeout(()=>{e.innerHTML=t,e.classList.remove("csk-action-btn--done")},1500)}catch(n){}}function P(n){n.querySelectorAll(".csk-md-code-block").forEach(n=>{if(n.querySelector(".csk-md-code-copy"))return;const e=n.querySelector("code"),t=document.createElement("button");t.type="button",t.className="csk-md-code-copy",t.setAttribute("title",a("copy")),t.setAttribute("aria-label",a("copy")),t.innerHTML=q,t.addEventListener("click",async n=>{n.stopPropagation(),await j((null==e?void 0:e.textContent)||"",t)}),n.appendChild(t)})}function R(n,e){n.classList.remove("csk-msg--streaming");const t=e.querySelector(".csk-caret");t&&t.remove(),P(e)}function U(n,e){const t=n.querySelector(".csk-sources");if(t&&t.remove(),!e||0===e.length)return;const r=document.createElement("div");r.className="csk-sources csk-sources--collapsed";const s=document.createElement("div");s.className="csk-sources__header";const o=document.createElement("span");o.className="csk-sources__title",o.textContent=`📚 ${a("source_count",{n:e.length})}`;const i=document.createElement("span");i.className="csk-sources__arrow",i.textContent="▼",s.appendChild(o),s.appendChild(i),s.addEventListener("click",()=>{r.classList.toggle("csk-sources--collapsed")});const c=document.createElement("div");c.className="csk-sources__body";for(const n of e){const e=document.createElement("div");e.className="csk-source-item";const t=document.createElement("div");if(t.className="csk-source-item__name",t.textContent=n.title||n.sourceName||"未知文档",n.snippet){const t=document.createElement("div");t.className="csk-source-item__snippet",t.textContent=n.snippet,e.appendChild(t)}const r=document.createElement("div");r.className="csk-source-item__meta";const s=[];n.sourceName&&s.push(n.sourceName),void 0!==n.chunkIndex&&s.push(`分块 #${n.chunkIndex}`),void 0!==n.score&&s.push(`相关度 ${(100*n.score).toFixed(0)}%`),r.textContent=s.join(" · "),e.appendChild(t),e.appendChild(r),c.appendChild(e)}r.appendChild(s),r.appendChild(c);const l=n.querySelector(".csk-msg__time");l&&l.parentNode?l.parentNode.insertBefore(r,l):n.appendChild(r)}function Y(n,e,t,r,s,o,i){if(n.innerHTML="",0===e.length){const e=document.createElement("div");return e.className="csk-history-panel__empty",e.innerHTML=`\n <div class="csk-history-panel__empty-icon">💬</div>\n <div>${a("history_empty")}</div>\n `,void n.appendChild(e)}for(const i of e){const e=document.createElement("div");e.className="csk-history-item";const c=i.chatId||i.id;o&&c===o&&e.classList.add("csk-history-item--active");const l=document.createElement("div");l.className="csk-history-item__info";const d=document.createElement("div");d.className="csk-history-item__id",i.lastMessagePreview?d.textContent=i.lastMessagePreview.length>60?i.lastMessagePreview.substring(0,60)+"...":i.lastMessagePreview:d.textContent=c;const p=document.createElement("div");p.className="csk-history-item__meta";const u=[];void 0!==i.messageCount&&u.push(`${i.messageCount} 条消息`),i.lastMessageTime?u.push(i.lastMessageTime):i.createdAt&&u.push(i.createdAt),p.textContent=u.join(" · "),l.appendChild(d),l.appendChild(p);const k=document.createElement("div");k.className="csk-history-item__actions";const m=document.createElement("button");m.className="csk-history-action csk-history-action--export",m.setAttribute("title",a("history_export")),m.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>',m.addEventListener("click",n=>{n.stopPropagation(),r(i.id)});const g=document.createElement("button");g.className="csk-history-action csk-history-action--delete",g.setAttribute("title",a("history_delete")),g.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>',g.addEventListener("click",n=>{n.stopPropagation(),s(i.id)}),k.appendChild(m),k.appendChild(g),e.appendChild(l),e.appendChild(k),e.addEventListener("click",()=>{t(c)}),n.appendChild(e)}}function O(n){n.scrollTop=n.scrollHeight}function W(n){const e=new Date(n);return`${String(e.getHours()).padStart(2,"0")}:${String(e.getMinutes()).padStart(2,"0")}`}function K(n){return`csk_history_${n}`}function V(n,e){try{let t=e;t.length>200&&(t=t.slice(50),r.warn(`消息数量达到上限,已裁剪最早 50 条,当前 ${t.length} 条`));const s={messages:t,updatedAt:Date.now()};localStorage.setItem(K(n),JSON.stringify(s))}catch(n){n instanceof Error&&"QuotaExceededError"===n.name?r.error("localStorage 空间不足,会话历史保存失败。建议清空历史记录。"):r.error("保存会话历史失败",n)}}function X(n){try{localStorage.removeItem(K(n))}catch(n){r.warn("清空会话历史失败",n)}}const G="\0CODEBLOCK_",J="\0INLINECODE_";function Q(n){if(!n||"string"!=typeof n)return"";const e=[];let t=n;t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(n,t,r)=>{const s=e.length,o=S(r.trimEnd()),a=t?` class="language-${S(t)}"`:"";return e.push(`<pre class="csk-md-code-block"><code${a}>${o}</code></pre>`),`${G}${s}\0`});const r=[];t=t.replace(/`([^`\n]+)`/g,(n,e)=>{const t=r.length;return r.push(`<code class="csk-md-inline-code">${S(e)}</code>`),`${J}${t}\0`}),t=S(t),t=Z(t,G,e),t=Z(t,J,r);const s=t.split("\n"),o=[];let a=!1,i="",c=!1,l=[];for(let n=0;n<s.length;n++){const e=s[n];if(e.includes(G)||e.includes('<pre class="csk-md-code-block">')){p(),u(),k(),o.push(e);continue}const t=e.match(/^(#{1,6})\s+(.+)/);if(t){p(),u(),k();const n=t[1].length;o.push(`<h${n} class="csk-md-h${n}">${t[2]}</h${n}>`);continue}const r=e.match(/^>\s?(.*)/);if(r){p(),u(),c||(c=!0,o.push('<blockquote class="csk-md-blockquote">')),o.push(`<p>${d(r[1])}</p>`);continue}c&&k();const m=e.match(/^[\-\*]\s+(.+)/);if(m){p(),k(),a&&"ul"===i||(u(),a=!0,i="ul",o.push('<ul class="csk-md-ul">')),o.push(`<li>${d(m[1])}</li>`);continue}const g=e.match(/^\d+\.\s+(.+)/);g?(p(),k(),a&&"ol"===i||(u(),a=!0,i="ol",o.push('<ol class="csk-md-ol">')),o.push(`<li>${d(g[1])}</li>`)):""!==e.trim()?/^(\*{3,}|-{3,}|_{3,})$/.test(e.trim())?(p(),u(),k(),o.push('<hr class="csk-md-hr">')):(u(),k(),l.push(d(e))):(p(),u())}return p(),u(),k(),o.join("\n");function d(n){return n=(n=(n=(n=(n=(n=n.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>")).replace(/__(.+?)__/g,"<strong>$1</strong>")).replace(/\*(.+?)\*/g,"<em>$1</em>")).replace(/(?<!\w)_(.+?)_(?!\w)/g,"<em>$1</em>")).replace(/~~(.+?)~~/g,"<del>$1</del>")).replace(/\[([^\]]+)\]\(([^)]+)\)/g,(n,e,t)=>`<a class="csk-md-link" href="${/^https?:\/\//i.test(t)?t:"#"}" target="_blank" rel="noopener noreferrer">${e}</a>`)}function p(){l.length>0&&(o.push(`<p class="csk-md-p">${l.join("<br>")}</p>`),l=[])}function u(){a&&(o.push("ul"===i?"</ul>":"</ol>"),a=!1,i="")}function k(){c&&(o.push("</blockquote>"),c=!1)}}function Z(n,e,t){return n.replace(new RegExp(e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"(\\d+)\0","g"),(n,e)=>t[parseInt(e)]||"")}let nn,en=null,tn=[],rn=null,sn=null,on=null,an=null,cn=null,ln=null,dn=null,pn=null,un=null,kn=null,mn=null,gn=null,hn=null,bn=!1,fn=null,yn=!0,xn=[],vn="",wn=!1;function _n(n,e){en=n,rn=e.messagesContainer,sn=e.inputEl,on=e.inputEl.parentElement,an=e.sendBtn,cn=e.clearBtn,ln=e.categorySelect,dn=e.historyPanel,pn=e.welcomeEl,un=e.newMsgBtn,kn=e.searchInput,mn=e.ariaLiveEl,gn=e.showLoading,hn=e.hideLoading,nn=n.categoryId,wn=!!n.categoryId||!!n.showCategorySwitch,function(){if(!sn||!an)return;an.addEventListener("click",()=>{bn&&fn?fn.abort():Fn()}),sn.addEventListener("keydown",n=>{"Enter"!==n.key||n.shiftKey||n.isComposing||(n.preventDefault(),Fn())}),sn.addEventListener("input",()=>{Sn(),function(){if(!sn)return;sn.style.height="auto",sn.style.height=`${Math.min(sn.scrollHeight,120)}px`}()}),sn.addEventListener("focus",()=>{on&&on.classList.add("csk-input-wrap--focus")}),sn.addEventListener("blur",()=>{on&&on.classList.remove("csk-input-wrap--focus")}),cn&&cn.addEventListener("click",()=>function(){if(!en)return;if(!confirm(a("clear_confirm")))return;if(tn=[],rn){rn.querySelectorAll(".csk-msg, .csk-loading").forEach(n=>n.remove())}cn&&(cn.style.display="none");Ln(),X(en.integrateId);const n=function(){const n="undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID().substring(0,8):Math.random().toString(36).substring(2,10);return`sdk_${Date.now()}_${n}`}();c(n),E(en.integrateId,en.userId,n),r.lifecycleClear(en.integrateId),r.info(`新 chatId=${n}`)}())}(),function(){if(!rn)return;rn.addEventListener("scroll",()=>{if(!rn)return;const{scrollTop:n,scrollHeight:e,clientHeight:t}=rn;yn=e-n-t<80,yn&&Cn()}),un&&un.addEventListener("click",()=>{rn&&O(rn),yn=!0,Cn()})}(),function(){if(!kn)return;kn.addEventListener("input",()=>{vn=kn.value.trim().toLowerCase(),An()})}(),n.showCategorySwitch&&ln&&async function(){if(!ln)return;try{const n=await async function(){const n=d("/category/tree");try{const e=await u(n);if(!e.ok)throw new k(m(e.status),`http_${e.status}`);const t=await e.json();return t.success&&Array.isArray(t.data)?(r.info(`加载分类树成功 count=${t.data.length}`),t.data):[]}catch(n){return n instanceof k?r.error(`加载分类树失败: ${n.message}`):r.error("加载分类树失败",n),[]}}();if(0===n.length)return;ln.innerHTML=`<option value="">${a("category_all")}</option>`;const e=(n,t=0)=>{for(const r of n){const n=document.createElement("option");n.value=String(r.id),n.textContent=`${" ".repeat(t)}${r.name}`,void 0!==nn&&String(r.id)===String(nn)&&(n.selected=!0),ln.appendChild(n),r.children&&r.children.length>0&&e(r.children,t+1)}};e(n),r.info(`知识库分类加载成功 count=${n.length}`)}catch(n){r.error(a("category_load_error"),n)}}()}async function En(){if(en&&rn&&(await w(),await async function(){if(!en||!rn)return;const n=l();if(!n)return;try{const e=await y(n);e.messages.length>0&&(tn=e.messages.map((n,e)=>({id:L(),role:"USER"===n.messageType?"user":"ai",content:n.content,timestamp:new Date(n.createTime).getTime()})),Mn(),r.info(`从后端加载 ${tn.length} 条历史消息`),V(en.integrateId,tn))}catch(n){r.warn("从后端加载历史消息失败",n)}}(),0===tn.length)){const n=function(n){try{const e=localStorage.getItem(K(n));if(!e)return[];const t=JSON.parse(e);return t&&Array.isArray(t.messages)?(r.info(`加载历史消息 integrateId=${n} count=${t.messages.length}`),t.messages):[]}catch(n){return r.warn("加载会话历史失败",n),[]}}(en.integrateId);n.length>0&&(tn=n,Mn(),r.info(`从本地缓存恢复 ${n.length} 条消息`))}}function Cn(){un&&un.classList.add("csk-newmsg--hidden")}function In(){rn&&(yn?O(rn):un&&un.classList.remove("csk-newmsg--hidden"))}function $n(n){an&&("stop"===n?(an.classList.add("csk-send-btn--stop"),an.removeAttribute("disabled"),an.setAttribute("title",a("stop")),an.setAttribute("aria-label",a("stop")),an.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>'):(an.classList.remove("csk-send-btn--stop"),an.setAttribute("title",a("send")),an.setAttribute("aria-label",a("send")),an.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>',Sn()))}function An(){const n=null==dn?void 0:dn.querySelector("#csk-history-list");if(!n||!en)return;Y(n,vn?xn.filter(n=>(n.lastMessagePreview||n.chatId||n.id||"").toLowerCase().includes(vn)):xn,n=>{Dn(n)},n=>{window.open(v(n),"_blank")},async n=>{if(!confirm(a("history_delete_confirm")))return;await x(n)&&(n===l()&&(tn=[],rn&&rn.querySelectorAll(".csk-msg, .csk-loading").forEach(n=>n.remove()),cn&&(cn.style.display="none"),Ln()),xn=xn.filter(e=>(e.chatId||e.id)!==n),An())},l())}function Ln(){if(!pn)return;const n=tn.length>0||rn&&rn.querySelector(".csk-msg");pn.style.display=n?"none":""}function Sn(){if(!an||!sn)return;sn.value.trim().length>0&&!bn?an.removeAttribute("disabled"):an.setAttribute("disabled","true")}async function Fn(){if(!sn||!en||bn)return;const n=sn.value.trim();if(""===n)return;sn.value="",Sn(),sn.style.height="auto";const e=F(),t={id:L(),role:"user",content:n,timestamp:e};rn&&D(rn,n,e),tn.push(t),Ln(),cn&&tn.length>0&&(cn.style.display="inline-flex"),rn&&In(),await Nn(n)}async function Nn(n){if(!en||!rn)return;bn=!0,$n("stop"),en.chatId||await w();const e=F(),t=wn&&(void 0!==nn||void 0!==en.categoryId);gn&&gn(),rn&&In();const s=L();let o="";try{en.streaming?o=await async function(n,e,t,r){fn=new AbortController;const s=fn.signal;return new Promise((o,i)=>{let c=null,l=null,d="",p=!1;h(n,n=>{if(d+=n,!p&&rn){hn&&hn();const{wrapper:n,bubble:t}=function(n,e,t){const r=document.createElement("div");r.className="csk-msg csk-msg--ai csk-msg--streaming",t&&(r.dataset.cskMsgId=t);const s=document.createElement("div");s.className="csk-msg__avatar csk-msg__avatar--ai",s.innerHTML=N;const o=document.createElement("div");o.className="csk-msg__content";const a=document.createElement("div");a.className="csk-msg__bubble",a.innerHTML="";const i=document.createElement("div");return i.className="csk-msg__time",i.textContent=W(e),o.appendChild(a),o.appendChild(B(a,r)),o.appendChild(i),r.appendChild(s),r.appendChild(o),n.appendChild(r),{wrapper:r,bubble:a}}(rn,e,r);l=n,c=t,p=!0}c&&(c.textContent=d,function(n){if(n.querySelector(".csk-caret"))return;const e=document.createElement("span");e.className="csk-caret",e.setAttribute("aria-hidden","true"),n.appendChild(e)}(c)),rn&&In()},()=>{if(l&&c){if(!p&&""===d)return void g(n).then(o).catch(i);d&&(c.innerHTML=Q(d)),R(l,c)}o(d)},n=>{d.length>0?(c&&(c.innerHTML=Q(d+"\n\n"+a("stream_interrupted")),l&&R(l,c)),o(d)):i(n)},nn,t,s)})}(n,e,t,s):(o=await g(n),hn&&hn(),rn&&T(rn,o,e,Q,s));const i={id:s,role:"ai",content:o,timestamp:e};tn.push(i),V(en.integrateId,tn),rn&&In(),function(n){if(!mn)return;const e=n.length>120?n.substring(0,120)+"...":n;mn.textContent=a("new_msg_announce")+":"+e}(o),rn&&rn.dispatchEvent(new CustomEvent("csk:newMessage",{bubbles:!0})),t&&async function(n,e){try{const t=await b(n,nn);if(t.length>0){const n=t.map(n=>{var e,t;return{documentId:n.documentId||"",title:n.title||"",sourceName:n.sourceName||"",chunkIndex:null!==(e=n.chunkIndex)&&void 0!==e?e:0,score:null!==(t=n.score)&&void 0!==t?t:0,snippet:n.snippet||""}});if(e.sources=n,rn){const e=rn.querySelector(".csk-msg--ai:last-of-type");e&&U(e,n)}en&&V(en.integrateId,tn)}}catch(n){r.warn("获取引用来源失败",n)}}(n,i)}catch(n){hn&&hn();const e=n instanceof k?n.message:a("error_send");if(rn){const n=document.createElement("div");n.className="csk-msg csk-msg--ai";const t=document.createElement("div");t.className="csk-msg__bubble",t.style.color="#DC2626",t.textContent=`⚠ ${e}`,n.appendChild(t),rn.appendChild(n)}r.error(`发送失败 integrateId=${en.integrateId}`,n)}finally{bn=!1,fn=null,$n("send"),Sn()}}function Mn(){if(!rn)return;const n=rn.querySelector(".csk-history-panel");rn.querySelectorAll(".csk-msg, .csk-loading").forEach(n=>n.remove());for(const n of tn)if("user"===n.role)D(rn,n.content,n.timestamp);else{const e=T(rn,n.content,n.timestamp,Q,n.id);n.sources&&n.sources.length>0&&U(e,n.sources),n.feedback&&H(e,n.feedback)}yn=!0,O(rn),cn&&tn.length>0&&(cn.style.display="inline-flex"),Ln(),n&&!rn.contains(n)&&rn.appendChild(n)}async function Dn(n){if(!en||!rn)return;r.info(`切换到会话 conversationId=${n}`),c(n),E(en.integrateId,en.userId,n),dn&&dn.classList.add("csk-history-panel--hidden"),tn=[];rn.querySelectorAll(".csk-msg, .csk-loading").forEach(n=>n.remove());try{const e=await y(n);e.messages.length>0&&(tn=e.messages.map(n=>({id:L(),role:"USER"===n.messageType?"user":"ai",content:n.content,timestamp:new Date(n.createTime).getTime()})),Mn(),r.info(`加载会话 ${n} 的 ${tn.length} 条消息`),V(en.integrateId,tn))}catch(e){r.warn(`加载会话消息失败 conversationId=${n}`,e)}cn&&tn.length>0&&(cn.style.display="inline-flex"),Ln()}let Tn=null,qn=!1,zn=null,Bn=null,Hn=null,jn=null,Pn=null,Rn=null,Un=null,Yn=null,On=null,Wn=null,Kn=null,Vn=null,Xn=null,Gn=null;function Jn(){if(!Vn||!zn)return;const n=zn.getBoundingClientRect();"left-bottom"===(null==Tn?void 0:Tn.position)?Vn.style.left=`${n.left}px`:Vn.style.right=window.innerWidth-n.right+"px",Vn.style.bottom=window.innerHeight-n.top+8+"px"}function Qn(){if(!Vn)return;Vn.classList.add("csk-teaser--hidden"),Vn.removeEventListener("click",Zn);const n=Vn.querySelector(".csk-teaser__close");n&&n.removeEventListener("click",ne)}function Zn(n){n.target.closest(".csk-teaser__close")||(Qn(),se())}function ne(n){n.stopPropagation(),Qn()}function ee(){Vn&&!Vn.classList.contains("csk-teaser--hidden")&&Jn()}const te='button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';function re(n){"Escape"===n.key&&Bn&&!Bn.classList.contains("csk-window--hidden")&&oe(),function(n){if(!Bn||Bn.classList.contains("csk-window--hidden"))return;if("Tab"!==n.key)return;const e=Array.from(Bn.querySelectorAll(te));if(0===e.length)return;const t=e[0],r=e[e.length-1];n.shiftKey?document.activeElement===t&&(n.preventDefault(),r.focus()):document.activeElement===r&&(n.preventDefault(),t.focus())}(n)}function se(){Bn&&(Bn.classList.remove("csk-window--hidden"),Qn(),Gn&&Gn.classList.add("csk-launcher__badge--hidden"),setTimeout(()=>{jn&&jn.focus()},80))}function oe(){Bn&&Bn.classList.add("csk-window--hidden")}function ae(){Bn&&(Bn.classList.contains("csk-window--hidden")?se():oe())}const ie={init:function(n){if(qn)return void r.warn("SDK 已初始化,请先调用 destroy() 再重新初始化");const t=function(n){var e,t,s,o,a,i,c;if(!n.integrateId||"string"!=typeof n.integrateId&&"number"!=typeof n.integrateId||"string"==typeof n.integrateId&&""===n.integrateId.trim())return r.error('integrateId 是必传参数(对应后端 roleId 客服角色 ID),请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;if(!n.requestDomain||"string"!=typeof n.requestDomain||""===n.requestDomain.trim())return r.error('requestDomain 是必传参数,请检查 init() 调用。示例:ChatbotSDK.init({ integrateId: 1, requestDomain: "https://api.example.com" })'),null;try{new URL(n.requestDomain)}catch(e){return r.error(`requestDomain 不是合法的 URL 格式:${n.requestDomain}。请提供完整的域名,如 https://api.example.com`),null}const l={integrateId:String(n.integrateId).trim(),requestDomain:n.requestDomain.replace(/\/+$/,""),userId:n.userId,categoryId:n.categoryId,showCategorySwitch:null!==(e=n.showCategorySwitch)&&void 0!==e&&e,title:n.title||"AI 智能助手",width:null!==(t=n.width)&&void 0!==t?t:380,position:"left-bottom"===n.position?"left-bottom":"right-bottom",primaryColor:n.primaryColor||"#4F46E5",launcherIcon:n.launcherIcon||'<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 32 32" fill="none">\n <defs>\n <linearGradient id="csk-ico-grad" x1="6" y1="8" x2="26" y2="28" gradientUnits="userSpaceOnUse">\n <stop offset="0%" stop-color="#fff" stop-opacity="1"/>\n <stop offset="100%" stop-color="#fff" stop-opacity="0.82"/>\n </linearGradient>\n </defs>\n <rect x="5" y="8" width="22" height="16" rx="4" fill="url(#csk-ico-grad)"/>\n <path d="M9 24L6 28.5l6-4.5z" fill="url(#csk-ico-grad)"/>\n <line x1="16" y1="8" x2="16" y2="4" stroke="#fff" stroke-width="1.5" stroke-linecap="round"/>\n <circle cx="16" cy="3" r="1.5" fill="#fff" class="csk-ico-antenna"/>\n <rect x="9.5" y="13" width="4" height="3.5" rx="1.2" fill="rgba(99,102,241,0.55)" class="csk-ico-eye"/>\n <rect x="18.5" y="13" width="4" height="3.5" rx="1.2" fill="rgba(99,102,241,0.55)" class="csk-ico-eye"/>\n <circle cx="11" cy="14.2" r="0.7" fill="#fff" opacity="0.9"/>\n <circle cx="20" cy="14.2" r="0.7" fill="#fff" opacity="0.9"/>\n <path d="M12.5 20 Q16 22.5 19.5 20" stroke="rgba(99,102,241,0.4)" stroke-width="1.2" fill="none" stroke-linecap="round"/>\n</svg>',showClear:null===(s=n.showClear)||void 0===s||s,showAdminPanel:null!==(o=n.showAdminPanel)&&void 0!==o&&o,quickReplies:Array.isArray(n.quickReplies)?n.quickReplies.map(n=>String(n).trim()).filter(Boolean):[],theme:"dark"===n.theme?"dark":"light",showTeaser:null===(a=n.showTeaser)||void 0===a||a,teaserText:"string"==typeof n.teaserText&&n.teaserText.trim()||"",streaming:null===(i=n.streaming)||void 0===i||i,locale:n.locale||"zh-CN",debug:null===(c=n.debug)||void 0===c||c,chatId:""};return r.info(`配置解析完成 integrateId(=roleId)=${l.integrateId} userId(=accountId)=${l.userId||"(未设置)"} requestDomain=${l.requestDomain}`),l}(n);if(!t)return;var c;Tn=t,function(n){if(s[n])o=n;else{const e=n.split("-")[0],t=Object.keys(s).find(n=>n.startsWith(e));t&&(o=t)}}(Tn.locale),c=Tn.debug,e=c,function(n){i=n}(Tn),A(Tn),zn=M(Tn,ae),document.body.appendChild(zn),Gn=zn.querySelector(".csk-launcher__badge");const d=function(n){const e=document.createElement("div");e.id="csk-window",e.className=`csk-root csk-window csk-window--${"left-bottom"===n.position?"left":"right"} csk-window--hidden${"dark"===n.theme?" csk-dark":""}`,e.setAttribute("role","dialog"),e.setAttribute("aria-label",n.title),e.setAttribute("aria-modal","false");const t=document.createElement("div");t.className="csk-header";const r=document.createElement("div");r.className="csk-header__left";const s=document.createElement("div");s.className="csk-header__avatar",s.innerHTML=N;const o=document.createElement("div");o.className="csk-header__info";const i=document.createElement("span");i.className="csk-header__title",i.textContent=n.title;const c=document.createElement("span");c.className="csk-header__status",c.innerHTML=`<i class="csk-status-dot"></i>${a("status_online")}`,o.appendChild(i),o.appendChild(c),r.appendChild(s),r.appendChild(o);const l=document.createElement("div");l.className="csk-header__actions";const d=document.createElement("button");d.className="csk-history-btn",d.setAttribute("title",a("history_title")),d.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>';const p=document.createElement("button");p.className="csk-header__btn csk-header__btn--minimize",p.setAttribute("title",a("minimize")),p.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/></svg>',p.addEventListener("click",()=>{e.classList.add("csk-window--hidden")});const u=document.createElement("button");u.className="csk-header__btn csk-header__btn--close",u.setAttribute("title",a("close")),u.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',u.addEventListener("click",()=>{e.classList.add("csk-window--hidden")}),l.appendChild(d),l.appendChild(p),l.appendChild(u),t.appendChild(r),t.appendChild(l);const k=document.createElement("div");k.id="csk-messages",k.className="csk-messages";const m=document.createElement("div");if(m.className="csk-welcome",m.innerHTML=`\n <div class="csk-welcome__avatar">${N}</div>\n <div class="csk-welcome__title">${a("welcome_title")}</div>\n <div class="csk-welcome__desc">${a("welcome_desc")}</div>\n `,n.quickReplies.length>0){const t=document.createElement("div");t.className="csk-quick-replies";for(const r of n.quickReplies){const n=document.createElement("button");n.type="button",n.className="csk-quick-reply",n.textContent=r,n.addEventListener("click",()=>{e.dispatchEvent(new CustomEvent("csk:quickReply",{detail:{text:r}}))}),t.appendChild(n)}m.appendChild(t)}k.appendChild(m);const g=document.createElement("button");g.type="button",g.className="csk-newmsg csk-newmsg--hidden",g.innerHTML=`\n <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>\n <span>${a("new_message")}</span>\n `,e.appendChild(g);const h=document.createElement("div");h.className="csk-history-panel csk-history-panel--hidden",h.innerHTML=`\n <div class="csk-history-panel__header">\n <span class="csk-history-panel__title">${a("history_title")}</span>\n <button class="csk-history-panel__back" id="csk-history-back">\n <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>\n ${a("close")}\n </button>\n </div>\n <div class="csk-history-panel__search-wrap">\n <input type="text" class="csk-history-panel__search" id="csk-history-search" placeholder="${a("history_search")}" />\n </div>\n <div class="csk-history-panel__list" id="csk-history-list"></div>\n `,k.appendChild(h);const b=h.querySelector("#csk-history-back");b&&b.addEventListener("click",()=>{h.classList.add("csk-history-panel--hidden")}),d.addEventListener("click",n=>{n.stopPropagation();const t=h.classList.contains("csk-history-panel--hidden");h.classList.toggle("csk-history-panel--hidden"),t&&e.dispatchEvent(new CustomEvent("csk:loadHistory"))});let f=null;if(n.showCategorySwitch){const n=document.createElement("div");n.className="csk-category-bar";const r=document.createElement("span");r.className="csk-category-bar__label",r.textContent="📚",f=document.createElement("select"),f.id="csk-category-select",f.className="csk-category-select",f.innerHTML=`<option value="">${a("category_all")}</option>`,f.addEventListener("change",()=>{const n=f.value;e.dispatchEvent(new CustomEvent("csk:categoryChange",{detail:{categoryId:n?Number(n):void 0}}))}),n.appendChild(r),n.appendChild(f),e.appendChild(t),e.appendChild(k),e.appendChild(n)}else e.appendChild(t),e.appendChild(k);const y=document.createElement("div");y.className="csk-input-area";const x=document.createElement("div");x.className="csk-input-wrap";const v=document.createElement("textarea");v.id="csk-input",v.className="csk-input",v.setAttribute("placeholder",a("placeholder")),v.setAttribute("rows","1"),v.setAttribute("autofocus","");const w=document.createElement("button");w.id="csk-send-btn",w.className="csk-send-btn",w.setAttribute("title",a("send")),w.setAttribute("disabled","true"),w.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>',x.appendChild(v),x.appendChild(w),y.appendChild(x),e.appendChild(y);let _=null;n.showClear&&(_=document.createElement("button"),_.className="csk-clear-btn",_.textContent=a("clear"),_.style.display="none",e.insertBefore(_,y));let E=null;const C=document.createElement("div");C.className="csk-sr-only",C.setAttribute("aria-live","polite"),C.setAttribute("aria-atomic","true"),e.appendChild(C);const I=h.querySelector("#csk-history-search"),$=document.createElement("div");return $.className=`csk-teaser csk-teaser--${"left-bottom"===n.position?"left":"right"} csk-teaser--hidden`,$.setAttribute("role","status"),$.innerHTML=`\n <button class="csk-teaser__close" aria-label="${a("close")}" type="button">×</button>\n <span>${n.teaserText||a("teaser_text")}</span>\n `,{window:e,messagesContainer:k,inputEl:v,sendBtn:w,clearBtn:_,categorySelect:f,historyPanel:h,welcomeEl:m,newMsgBtn:g,teaserEl:$,searchInput:I,ariaLiveEl:C,showLoading:function(){if(E)return E.style.display="flex",E;const n=document.createElement("div");return n.className="csk-loading",n.innerHTML=`\n <div class="csk-loading__avatar">${N}</div>\n <div class="csk-loading__bubble">\n <div class="csk-loading__dot"></div>\n <div class="csk-loading__dot"></div>\n <div class="csk-loading__dot"></div>\n </div>\n `,k.appendChild(n),E=n,n},hideLoading:function(){E&&E.parentNode&&(E.parentNode.removeChild(E),E=null)}}}(Tn);Bn=d.window,Hn=d.messagesContainer,jn=d.inputEl,Pn=d.sendBtn,Rn=d.clearBtn,Un=d.categorySelect,Yn=d.historyPanel,On=d.showLoading,Wn=d.hideLoading,document.body.appendChild(Bn),Vn=d.teaserEl,document.body.appendChild(Vn),Jn();const p=Bn.querySelector(".csk-header");p&&(Kn=function(n,e){let t=!1,r=0,s=0,o=0,a=0;const i=n=>{if(n.target.closest("button"))return;t=!0,r=n.clientX,s=n.clientY;const i=e.getBoundingClientRect();o=r-i.left,a=s-i.top,document.addEventListener("mousemove",c),document.addEventListener("mouseup",l)},c=n=>{if(!t)return;const r=n.clientX-o,s=n.clientY-a,i=window.innerWidth-e.offsetWidth,c=window.innerHeight-e.offsetHeight;e.style.right="auto",e.style.bottom="auto",e.style.left=`${Math.max(0,Math.min(r,i))}px`,e.style.top=`${Math.max(0,Math.min(s,c))}px`},l=()=>{t=!1,document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",l)};return n.addEventListener("mousedown",i),()=>{n.removeEventListener("mousedown",i),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",l)}}(p,Bn)),_n(Tn,{messagesContainer:Hn,inputEl:jn,sendBtn:Pn,clearBtn:Rn,categorySelect:Un,historyPanel:Yn,welcomeEl:d.welcomeEl,newMsgBtn:d.newMsgBtn,searchInput:d.searchInput,ariaLiveEl:d.ariaLiveEl,showLoading:On,hideLoading:Wn}),Bn.addEventListener("csk:categoryChange",n=>{var e;e=n.detail.categoryId,nn=e,wn=void 0!==e,r.lifecycleCategoryChange(null!=e?e:"全部")}),Bn.addEventListener("csk:loadHistory",()=>{!async function(){if(!dn||!en)return;const n=dn.querySelector("#csk-history-list");if(n){n.innerHTML='<div class="csk-history-panel__loading">加载中...</div>';try{const e=await f(1,50,en.userId,en.integrateId);xn=e.list.map(n=>({id:n.conversationId||"",chatId:n.conversationId||"",messageCount:n.messageCount,lastMessageTime:n.lastMessageTime,lastMessagePreview:n.lastMessagePreview,createdAt:n.firstMessageTime||n.createdAt})),vn="",kn&&(kn.value=""),Y(n,xn,n=>{Dn(n)},n=>{window.open(v(n),"_blank")},async n=>{confirm(a("history_delete_confirm"))&&await x(n)&&(n===l()&&(tn=[],rn&&rn.querySelectorAll(".csk-msg, .csk-loading").forEach(n=>n.remove()),cn&&(cn.style.display="none"),Ln()),xn=xn.filter(e=>(e.chatId||e.id)!==n),An())},l())}catch(e){r.error(a("history_load_error"),e),n.innerHTML=`<div class="csk-history-panel__empty"><div class="csk-history-panel__empty-icon">⚠</div><div>${a("history_load_error")}</div></div>`}}}()}),Bn.addEventListener("csk:quickReply",n=>{var e;e=n.detail.text,!sn||bn?Promise.resolve():(sn.value=e,Sn(),Fn())}),Bn.addEventListener("csk:retry",n=>{!async function(n){if(!en||!rn||bn)return;const e=tn.findIndex(e=>e.id===n&&"ai"===e.role);if(e<0)return;let t="";for(let n=e-1;n>=0;n--)if("user"===tn[n].role){t=tn[n].content;break}if(!t)return;const r=tn.splice(e),s=new Set(r.map(n=>n.id));rn.querySelectorAll(".csk-msg").forEach(n=>{const e=n.dataset.cskMsgId;e&&s.has(e)&&n.remove()}),V(en.integrateId,tn),Ln(),await Nn(t)}(n.detail.msgId)}),Bn.addEventListener("csk:feedback",n=>{!function(n,e){if(!rn)return;const t=tn.find(e=>e.id===n&&"ai"===e.role);if(!t)return;const s=t.feedback===e?void 0:e;t.feedback=s;const o=rn.querySelector(`[data-csk-msg-id="${n}"]`);o&&H(o,s),en&&V(en.integrateId,tn),r.info(`消息反馈 msgId=${n} value=${s||"cleared"}`)}(n.detail.msgId,n.detail.value)}),Bn.addEventListener("csk:newMessage",()=>{Bn&&Bn.classList.contains("csk-window--hidden")&&Gn&&Gn.classList.remove("csk-launcher__badge--hidden")}),document.addEventListener("keydown",re),window.addEventListener("resize",ee),qn=!0,r.lifecycleInit(Tn.integrateId,Tn.requestDomain),Tn.showTeaser&&(Xn=setTimeout(()=>{Bn&&Bn.classList.contains("csk-window--hidden")&&function(){if(!Vn)return;Jn(),Vn.classList.remove("csk-teaser--hidden"),Vn.addEventListener("click",Zn);const n=Vn.querySelector(".csk-teaser__close");n&&n.addEventListener("click",ne)}()},1500)),En().catch(n=>{r.warn("chatId 初始化失败,将在发送消息时重试",n)})},destroy:function(){if(!qn)return;Xn&&(clearTimeout(Xn),Xn=null),Qn(),Vn&&Vn.parentNode&&(Vn.parentNode.removeChild(Vn),Vn=null),zn&&zn.parentNode&&(zn.parentNode.removeChild(zn),zn=null),Bn&&Bn.parentNode&&(Bn.parentNode.removeChild(Bn),Bn=null),Kn&&(Kn(),Kn=null),C&&C.parentNode&&(C.parentNode.removeChild(C),C=null),document.querySelectorAll("style[data-csk-sdk]").forEach(n=>n.remove()),document.removeEventListener("keydown",re),window.removeEventListener("resize",ee);const n=null==Tn?void 0:Tn.integrateId;Tn=null,qn=!1,Hn=null,jn=null,Pn=null,Rn=null,Un=null,Yn=null,On=null,Wn=null,Gn=null,r.lifecycleDestroy(n||"")},open:se,close:oe,toggle:ae,clearHistory:function(){Tn&&(Rn?Rn.click():confirm("确定清空所有对话记录?")&&X(Tn.integrateId))}};return"undefined"!=typeof window&&(window.ChatbotSDK=ie),ie}();
|
|
//# sourceMappingURL=chatbot-sdk.min.js.map
|