koishi-plugin-chat-patch 1.0.14 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,8 +23,9 @@ export function useChatLogic() {
23
23
  id: string
24
24
  name: string
25
25
  type: number | string
26
- guildId?: string
26
+ channelId?: string
27
27
  guildName?: string
28
+ isDirect?: boolean
28
29
  }
29
30
 
30
31
  interface MessageElement {
@@ -306,6 +307,13 @@ export function useChatLogic() {
306
307
  'width': 'auto',
307
308
  'height': 'auto',
308
309
  'object-fit': 'contain'
310
+ },
311
+ // 确保GIF动画能正常播放
312
+ onLoad: () => {
313
+ // 对于GIF图片,确保动画开始播放
314
+ if (imgRef.value && props.src.toLowerCase().includes('.gif')) {
315
+ imgRef.value.style.imageRendering = 'auto'
316
+ }
309
317
  }
310
318
  })
311
319
 
@@ -904,6 +912,9 @@ export function useChatLogic() {
904
912
  selectedBot.value = botId
905
913
  selectedChannel.value = ''
906
914
 
915
+ // 保存选择状态
916
+ saveSelectionState()
917
+
907
918
  // 手机端:选择机器人后切换到频道视图
908
919
  if (isMobile.value) {
909
920
  mobileView.value = 'channels'
@@ -1094,6 +1105,9 @@ export function useChatLogic() {
1094
1105
  selectedChannel.value = channelId
1095
1106
  isUserScrolling.value = false
1096
1107
 
1108
+ // 保存选择状态
1109
+ saveSelectionState()
1110
+
1097
1111
  // 手机端:选择频道后切换到消息视图
1098
1112
  if (isMobile.value) {
1099
1113
  mobileView.value = 'messages'
@@ -1207,7 +1221,19 @@ export function useChatLogic() {
1207
1221
  event.preventDefault()
1208
1222
  const file = item.getAsFile()
1209
1223
  if (file) {
1210
- await uploadImage(file)
1224
+ // 为粘贴的文件创建一个带有正确扩展名的新File对象
1225
+ const extension = item.type === 'image/gif' ? '.gif' :
1226
+ item.type === 'image/png' ? '.png' :
1227
+ item.type === 'image/jpeg' ? '.jpg' : '.jpg'
1228
+ const filename = `pasted-image-${Date.now()}${extension}`
1229
+
1230
+ // 创建新的File对象,确保有正确的文件名和类型
1231
+ const newFile = new File([file], filename, {
1232
+ type: item.type,
1233
+ lastModified: Date.now()
1234
+ })
1235
+
1236
+ await uploadImage(newFile)
1211
1237
  }
1212
1238
  }
1213
1239
  }
@@ -1237,7 +1263,8 @@ export function useChatLogic() {
1237
1263
  const result = await (send as any)('upload-image', {
1238
1264
  file: base64,
1239
1265
  filename: file.name,
1240
- mimeType: file.type
1266
+ mimeType: file.type,
1267
+ isGif: file.type === 'image/gif' // 标记是否为GIF
1241
1268
  })
1242
1269
 
1243
1270
  if (result.success) {
@@ -2224,6 +2251,8 @@ export function useChatLogic() {
2224
2251
  byteNumbers[i] = byteCharacters.charCodeAt(i)
2225
2252
  }
2226
2253
  const byteArray = new Uint8Array(byteNumbers)
2254
+
2255
+ // 保持原始MIME类型,特别是对于GIF
2227
2256
  const blob = new Blob([byteArray], { type: contentType })
2228
2257
 
2229
2258
  // 检查blob大小
@@ -2339,6 +2368,31 @@ export function useChatLogic() {
2339
2368
  })
2340
2369
  }
2341
2370
 
2371
+ // 保存和恢复选择状态
2372
+ function saveSelectionState() {
2373
+ if (selectedBot.value && selectedChannel.value) {
2374
+ localStorage.setItem('chat-selected-bot', selectedBot.value)
2375
+ localStorage.setItem('chat-selected-channel', selectedChannel.value)
2376
+ }
2377
+ }
2378
+
2379
+ function restoreSelectionState() {
2380
+ const savedBot = localStorage.getItem('chat-selected-bot')
2381
+ const savedChannel = localStorage.getItem('chat-selected-channel')
2382
+
2383
+ if (savedBot && savedChannel) {
2384
+ // 验证保存的状态是否仍然有效
2385
+ if (chatData.value.bots[savedBot] &&
2386
+ chatData.value.channels[savedBot] &&
2387
+ chatData.value.channels[savedBot][savedChannel]) {
2388
+ selectedBot.value = savedBot
2389
+ selectedChannel.value = savedChannel
2390
+ return true
2391
+ }
2392
+ }
2393
+ return false
2394
+ }
2395
+
2342
2396
  // 处理消息事件
2343
2397
  function handleMessageEvent(messageEvent: any) {
2344
2398
  // 更新机器人信息
@@ -2368,16 +2422,17 @@ export function useChatLogic() {
2368
2422
  }
2369
2423
 
2370
2424
  if (messageEvent.channelId && !chatData.value.channels[messageEvent.selfId][messageEvent.channelId]) {
2371
- const channelName = messageEvent.guildId
2372
- ? `${messageEvent.guildName || messageEvent.guildId} (${messageEvent.channelId})`
2373
- : `私信 ${messageEvent.channelId}`
2425
+ const channelName = messageEvent.isDirect
2426
+ ? `私信 ${messageEvent.channelId}`
2427
+ : `${messageEvent.guildName || messageEvent.channelId} (${messageEvent.channelId})`
2374
2428
 
2375
2429
  chatData.value.channels[messageEvent.selfId][messageEvent.channelId] = {
2376
2430
  id: messageEvent.channelId,
2377
2431
  name: channelName,
2378
2432
  type: messageEvent.channelType || 0,
2379
- guildId: messageEvent.guildId,
2380
- guildName: messageEvent.guildName || messageEvent.guildId || '私聊'
2433
+ channelId: messageEvent.channelId,
2434
+ guildName: messageEvent.guildName || '群聊',
2435
+ isDirect: messageEvent.isDirect
2381
2436
  }
2382
2437
  }
2383
2438
 
@@ -2561,16 +2616,17 @@ export function useChatLogic() {
2561
2616
  }
2562
2617
 
2563
2618
  if (botMessageEvent.channelId && !chatData.value.channels[botMessageEvent.selfId][botMessageEvent.channelId]) {
2564
- const channelName = botMessageEvent.guildId
2565
- ? `${botMessageEvent.guildName || botMessageEvent.guildId} (${botMessageEvent.channelId})`
2566
- : `私信 ${botMessageEvent.channelId}`
2619
+ const channelName = botMessageEvent.isDirect
2620
+ ? `私信 ${botMessageEvent.channelId}`
2621
+ : `${botMessageEvent.guildName || botMessageEvent.channelId} (${botMessageEvent.channelId})`
2567
2622
 
2568
2623
  chatData.value.channels[botMessageEvent.selfId][botMessageEvent.channelId] = {
2569
2624
  id: botMessageEvent.channelId,
2570
2625
  name: channelName,
2571
2626
  type: botMessageEvent.channelType || 0,
2572
- guildId: botMessageEvent.guildId,
2573
- guildName: botMessageEvent.guildName || botMessageEvent.guildId || '私聊'
2627
+ channelId: botMessageEvent.channelId,
2628
+ guildName: botMessageEvent.guildName || '群聊',
2629
+ isDirect: botMessageEvent.isDirect
2574
2630
  }
2575
2631
  }
2576
2632
 
@@ -2980,6 +3036,14 @@ export function useChatLogic() {
2980
3036
  // 然后加载历史数据
2981
3037
  await loadChatData()
2982
3038
 
3039
+ // 尝试恢复之前的选择状态
3040
+ nextTick(() => {
3041
+ if (!restoreSelectionState()) {
3042
+ // 如果没有保存的状态或状态无效,则使用默认逻辑
3043
+ // 不自动选择任何频道,让用户手动选择
3044
+ }
3045
+ })
3046
+
2983
3047
  // 然后开始监听消息事件
2984
3048
  const dispose1 = receive('chat-message-event', handleMessageEvent) as (() => void) | undefined
2985
3049
  const dispose2 = receive('bot-message-sent-event', handleBotMessageSentEvent) as (() => void) | undefined
@@ -3151,6 +3215,8 @@ export function useChatLogic() {
3151
3215
  // 其他工具函数
3152
3216
  isFileUrl,
3153
3217
  loadHistoryMessages,
3154
- handleMessageEvent
3218
+ handleMessageEvent,
3219
+ saveSelectionState,
3220
+ restoreSelectionState
3155
3221
  }
3156
3222
  }
@@ -624,13 +624,27 @@
624
624
  max-width: min(400px, 66.67vw);
625
625
  max-height: 200px;
626
626
  width: auto;
627
- height: auto
627
+ height: auto;
628
+ /* 确保GIF动画正常播放 */
629
+ image-rendering: auto;
630
+ -webkit-image-rendering: auto;
631
+ -moz-image-rendering: auto;
632
+ -o-image-rendering: auto;
628
633
  }
629
634
 
630
635
  .message-image:hover {
631
636
  transform: scale(1.02)
632
637
  }
633
638
 
639
+ /* 专门针对GIF图片的样式 */
640
+ .message-image[src*=".gif"],
641
+ .message-image[src*="image/gif"] {
642
+ /* 确保GIF动画不被优化掉 */
643
+ image-rendering: auto !important;
644
+ -webkit-image-rendering: auto !important;
645
+ animation-play-state: running !important;
646
+ }
647
+
634
648
  .message-image-loading {
635
649
  display: inline-block;
636
650
  padding: 8px 12px;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{defineComponent as Ce,ref as v,onMounted as nt,h,computed as Q,watch as kt,nextTick as Ie,onUnmounted as ma,createElementBlock as x,openBlock as y,unref as r,normalizeStyle as st,normalizeClass as re,createElementVNode as f,createCommentVNode as xe,Fragment as E,renderList as De,createBlock as Ne,toDisplayString as _,withDirectives as bt,createTextVNode as ot,vShow as va,withModifiers as St,withKeys as ga,isRef as ya,vModelText as pa,resolveComponent as wa}from"vue";import{receive as rt,send as P,icons as Ia}from"@koishijs/client";function xa(){function ee(e){try{return new URL(e).protocol==="file:"}catch{return false}}const le=Ce({props:{src:{type:String,required:true},alt:{type:String,default:"头像"},channelKey:{type:String,required:true}},setup(e){const t=v("loading"),a=v(e.src),n=v(""),o=async()=>{try{t.value="loading";const i=await Ve(e.channelKey,e.src);if(i){a.value=i,t.value="loaded";return}const c=new Image;c.crossOrigin="anonymous",c.referrerPolicy="no-referrer",c.draggable=false;const d=new Promise((k,w)=>{c.onload=()=>k(),c.onerror=()=>w(new Error("Direct load failed")),c.src=e.src}),p=new Promise((k,w)=>{setTimeout(()=>w(new Error("Timeout")),3e3)});try{await Promise.race([d,p]),a.value=e.src,t.value="loaded",we(e.channelKey,e.src).catch(k=>{console.warn("异步缓存头像失败:",k)})}catch{await s()}}catch(i){console.error("头像加载失败:",i),t.value="error",n.value="头像加载失败"}},s=async()=>{try{t.value="caching";const i=await we(e.channelKey,e.src);if(i)a.value=i,t.value="loaded";else throw new Error("缓存系统加载失败")}catch(i){console.error("缓存系统加载头像失败:",i),t.value="error",n.value=(i==null?void 0:i.message)||"缓存加载失败"}};return nt(()=>{o()}),()=>{switch(t.value){case"loading":case"caching":return h("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase());case"loaded":return h("img",{src:a.value,alt:e.alt,draggable:false,style:{width:"100%",height:"100%","object-fit":"cover"}});case"error":return h("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase());default:return h("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase())}}}}),X=Ce({props:{src:{type:String,required:true},alt:{type:String,default:"图片"},filename:{type:String,default:""},channelKey:{type:String,required:true}},setup(e){const t=v("loading"),a=v(e.src),n=v(""),o=v(null),s=async()=>{try{t.value="loading";const c=await Ve(e.channelKey,e.src);if(c){a.value=c,t.value="loaded";return}if(ee(e.src)){console.log("ImageComponent: 检测到本地文件,使用代理请求:",e.src),await i();return}const d=new Image;d.crossOrigin="anonymous",d.referrerPolicy="no-referrer",d.draggable=false;const p=new Promise((w,R)=>{d.onload=()=>w(),d.onerror=()=>R(new Error("Direct load failed")),d.src=e.src}),k=new Promise((w,R)=>{setTimeout(()=>R(new Error("Timeout")),3e3)});try{await Promise.race([p,k]),a.value=e.src,t.value="loaded",we(e.channelKey,e.src).catch(w=>{console.warn("异步缓存图片失败:",w)})}catch{await i()}}catch(c){console.error("图片加载失败:",c),t.value="error",n.value="图片加载失败"}},i=async()=>{try{t.value="caching";const c=await we(e.channelKey,e.src);if(c)a.value=c,t.value="loaded";else throw new Error("缓存系统加载失败")}catch(c){console.error("缓存系统加载图片失败:",c),t.value="error",n.value=(c==null?void 0:c.message)||"缓存加载失败"}};return nt(()=>{s()}),()=>{switch(t.value){case"loading":return h("div",{class:"message-image-loading"},"加载中...");case"caching":return h("div",{class:"message-image-loading"},"[图片加载缓存中...]");case"loaded":return h("img",{src:a.value,alt:e.alt,class:"message-image",loading:"lazy",ref:o,draggable:false,style:{"max-width":"min(400px, 66.67vw)","max-height":"200px",width:"auto",height:"auto","object-fit":"contain"}});case"error":return h("div",{class:"message-image-error"},["图片加载失败",h("br"),h("small",e.filename||e.alt||"未知图片"),h("br"),h("small",{style:"color: #ff9800;"},n.value)]);default:return h("div",{class:"message-image-error"},"未知状态")}}}}),ge=Ce({props:{data:{type:String,required:true},channelKey:{type:String,required:true}},setup(e){const a=(()=>{try{const o=JSON.parse(e.data);if(o.meta&&o.meta.detail_1){const s=o.meta.detail_1;return{type:"share_card",title:s.title||o.prompt||"分享内容",desc:s.desc||"",preview:s.preview?s.preview.replace(/\\\//g,"/"):"",icon:s.icon?s.icon.replace(/\\\//g,"/"):"",url:s.qqdocurl?s.qqdocurl.replace(/\\\//g,"/"):s.url?s.url.replace(/\\\//g,"/"):"",appName:s.title||"应用"}}return{type:"raw",data:o}}catch(o){return console.error("解析JSON数据失败:",o),{type:"error",error:"无法解析的JSON数据"}}})(),n=()=>{a.type==="share_card"&&a.url&&window.open(a.url,"_blank","noopener,noreferrer")};return()=>a.type==="share_card"&&a.preview?h("img",{src:a.preview,alt:a.title||"[分享小程序]",class:"message-image",loading:"lazy",draggable:false,onClick:n,style:{"max-width":"400px","max-height":"200px",width:"auto",height:"auto","object-fit":"contain",cursor:a.url?"pointer":"default"},title:a.url?`点击打开: ${a.title||"链接"}`:a.title,onError:o=>{const i=o.target.parentElement;i&&(i.style.display="none")}}):a.type==="error"?h("div",{class:"message-json-error"},[h("span",{class:"json-error-text"},a.error),h("details",{class:"json-raw-data"},[h("summary","查看原始数据"),h("pre",{class:"json-raw-content"},e.data)])]):h("div",{class:"message-json-raw"},[h("div",{class:"json-label"},"[JSON数据]"),h("details",{class:"json-raw-data"},[h("summary","查看详情"),h("pre",{class:"json-raw-content"},JSON.stringify(a.data,null,2))])])}}),G=Ce({props:{element:{type:Object,required:true},channelKey:{type:String,required:true}},setup(e){const t=v(false),a=()=>{t.value=!t.value},n=()=>{if(!e.element.children||e.element.children.length===0)return{previews:[],messageCount:0};const s=e.element.children.filter(d=>d.type==="message"),i=s.length;return{previews:s.slice(0,3).map(d=>{var w,R;const p=((w=d.attrs)==null?void 0:w.nickname)||"用户";let k="";if(d.children&&d.children.length>0){const z=d.children[0];z.type==="text"?(k=(((R=z.attrs)==null?void 0:R.content)||"").substring(0,20),k.length>15&&(k+="...")):z.type==="img"?k="[图片]":z.type==="video"?k="[视频]":k=`[${z.type}]`}return`${p}:${k}`}),messageCount:i}},o=(s,i)=>{var p,k,w;const c=((p=s.attrs)==null?void 0:p.nickname)||"用户",d=((k=s.attrs)==null?void 0:k.userId)||"unknown";return h("div",{key:i,class:"forwarded-message-item"},[h("div",{class:"forwarded-message-header"},[h("span",{class:"forwarded-message-nickname"},c),h("span",{class:"forwarded-message-userid"},`(${d})`)]),h("div",{class:"forwarded-message-content"},((w=s.children)==null?void 0:w.map((R,z)=>h(ke,{key:z,element:R,channelKey:e.channelKey})))||[])])};return()=>{var c;const{previews:s,messageCount:i}=n();return h("div",{class:"forward-message-container"},[h("div",{class:"forward-message-preview",onClick:a},[h("div",{class:"forward-message-title"},"聊天记录"),...s.map((d,p)=>h("div",{key:p,class:"forward-message-preview-item"},d)),h("div",{class:"forward-message-footer"},[h("span",{class:"forward-message-count"},`查看${i}条转发消息`),h("span",{class:"forward-message-toggle"},t.value?"▲":"▼")])]),t.value&&h("div",{class:"forward-message-expanded"},((c=e.element.children)==null?void 0:c.filter(d=>d.type==="message").map((d,p)=>o(d,p)))||[])])}}}),ke=Ce({props:{element:{type:Object,required:true},channelKey:{type:String,required:true}},setup(e){const t=a=>{var n,o,s,i,c,d;switch(a.type){case"text":return h("span",{class:"message-text-content"},a.attrs.content||"");case"forward":return h("span",{class:"message-text-content"},`[转发消息 ${a.attrs.id}]`||"[转发消息]");case"img":case"image":const p=a.attrs.src||a.attrs.url||a.attrs.file;return h("div",{class:"message-image-container"},[h(X,{src:p,alt:a.attrs.summary||"图片",filename:a.attrs.filename||a.attrs.summary||"",channelKey:e.channelKey})]);case"mface":const k=a.attrs.src||a.attrs.url||a.attrs.file;return h("div",{class:"message-image-container"},[h(X,{src:k,alt:a.attrs.summary||"表情",filename:a.attrs.emojiId||a.attrs.summary||"",channelKey:e.channelKey})]);case"face":if((o=(n=a.children[0])==null?void 0:n.attrs)!=null&&o.src){const w=((i=(s=a.children[0])==null?void 0:s.attrs)==null?void 0:i.src)||((d=(c=a.children[0])==null?void 0:c.attrs)==null?void 0:d.url);return h("div",{class:"message-image-container"},[h(X,{src:w,alt:a.attrs.name||a.attrs.id||"[表情]",filename:a.attrs.name||a.attrs.id||"[表情]",channelKey:e.channelKey})])}else return h("span",{class:"message-text-content"},`[${a.attrs.name||a.attrs.id}]`||"[表情]");case"at":return h("span",{class:"message-at",title:a.attrs.name},`${a.attrs.name||a.attrs.id}`);case"json":return h("div",{class:"message-image-container"},[h(ge,{data:a.attrs.data||"",channelKey:e.channelKey})]);case"p":if(a.children&&a.children.length>0){const w=a.children.map((R,z)=>h(ke,{key:z,element:R,channelKey:e.channelKey}));return h("div",{class:"message-paragraph"},w)}else return h("div",{class:"message-paragraph"},"");case"figure":return h(G,{element:a,channelKey:e.channelKey});default:return h("span",{class:"message-unknown",title:`未知消息类型: ${a.type}`},a.attrs.content||`[${a.type}]`)}};return()=>t(e.element)}}),u=v({bots:{},channels:{},messages:{}}),q=v({}),ce=v({maxMessagesPerChannel:1e3,keepMessagesOnClear:50,loggerinfo:false,blockedPlatforms:[],chatContainerHeight:80}),b=v({}),be=100*1024*1024,ie=50;let ye=0,I=null;const Re="ChatImageCache",Oe=2,S="images",te=50*1024*1024,U=100,ue=500,Te=2*1024*1024,Fe=.8,We=60*1e3;let O=0,K=0,He=0;const g=v(""),$=v(""),Se=v(""),Y=v([]),de=v(false),Le=v(),L=v(false),V=v("bots"),F=v(null),ae=v(null),Be=v(false),fe=v({show:false,text:""}),B=v(),he=v(),$e=v(false),ne=v(false),me=v(false),se=v(""),M=v({x:0,y:0}),A=v({x:0,y:0}),_e=v({x:0,y:0}),pe=v({x:0,y:0}),H=80,qe=v(0),j=v(null),Z=v(false),C=v(null),N=v({show:false,x:0,y:0,type:null,targetId:"",isSecondClick:false}),W=v(new Set),oe=v(new Set),m=Q(()=>Object.values(u.value.bots).sort((t,a)=>{const n=W.value.has(t.selfId),o=W.value.has(a.selfId);return n&&!o?-1:!n&&o?1:0})),l=Q(()=>!g.value||!u.value.channels[g.value]?[]:Object.values(u.value.channels[g.value]).sort((t,a)=>{const n=oe.value.has(`${g.value}:${t.id}`),o=oe.value.has(`${g.value}:${a.id}`);return n&&!o?-1:!n&&o?1:0})),D=Q(()=>{if(!g.value||!$.value)return[];const e=`${g.value}:${$.value}`,t=u.value.messages[e]||[];return t.filter(a=>a.quote),t}),Ue=Q(()=>{var t;if(!g.value||!$.value)return"";const e=u.value.channels[g.value];return((t=e==null?void 0:e[$.value])==null?void 0:t.name)||""}),$t=Q(()=>!g.value||!$.value?"":`${g.value}:${$.value}`),lt=Q(()=>g.value&&$.value&&(Se.value.trim()||Y.value.length>0)&&!me.value),_t=Q(()=>g.value&&$.value&&!me.value),Dt=Q(()=>{if(!L.value)return"";switch(V.value){case"channels":return"show-channels";case"messages":return"show-messages";default:return""}}),Tt=Q(()=>L.value?"输入消息...(屏幕左滑返回)":"输入消息..."),Lt=Q(()=>({}));function ct(e){return e.size||0}function Xe(e){ye+=e,ce.value.loggerinfo&&console.log(`内存使用量变化: ${e>0?"+":""}${(e/1024/1024).toFixed(2)}MB, 总计: ${(ye/1024/1024).toFixed(2)}MB`)}function it(e=10){const t=Object.entries(b.value);if(t.length<=e)return;const a=t.slice(0,t.length-e);let n=0;a.forEach(([o,s])=>{URL.revokeObjectURL(s),delete b.value[o],n+=500*1024,ce.value.loggerinfo&&console.log("清理旧blob URL:",o)}),Xe(-n)}function Je(){Object.keys(b.value).length>ie&&it(Math.floor(ie*.7)),ye>be&&it(Math.floor(ie*.5))}function qt(e){g.value=e,$.value="",L.value&&(V.value="channels")}function Ut(e,t){if(e.preventDefault(),e.stopPropagation(),N.value.show&&N.value.type==="bot"&&N.value.targetId===t){J();return}Ge(e,"bot",t)}function Kt(e,t){if(e.preventDefault(),e.stopPropagation(),N.value.show&&N.value.type==="channel"&&N.value.targetId===t){J();return}Ge(e,"channel",t)}function Ge(e,t,a){let s=e.clientX,i=e.clientY;s+180>window.innerWidth&&(s=window.innerWidth-180-10),i+80>window.innerHeight&&(i=window.innerHeight-80-10),N.value={show:true,x:s,y:i,type:t,targetId:a,isSecondClick:false},document.addEventListener("click",J,{once:true}),document.addEventListener("keydown",Ze)}function J(){N.value.show=false,document.removeEventListener("click",J),document.removeEventListener("keydown",Ze)}function Ze(e){e.key==="Escape"&&N.value.show&&J()}async function Mt(e){W.value.has(e)?W.value.delete(e):W.value.add(e),await P("set-pinned-bots",{pinnedBots:Array.from(W.value)}),J()}async function At(e){const t=`${g.value}:${e}`;oe.value.has(t)?oe.value.delete(t):oe.value.add(t),await P("set-pinned-channels",{pinnedChannels:Array.from(oe.value)}),J()}async function zt(e){try{const t=await P("delete-bot-data",{selfId:e});if(t.success){const a=Object.keys(u.value.messages).filter(n=>n.startsWith(`${e}:`));for(const n of a)delete u.value.messages[n],delete q.value[n],await je(n);delete u.value.bots[e],delete u.value.channels[e],g.value===e&&(g.value="",$.value=""),T(t.message||"已删除该机器人的所有数据","success")}else throw new Error(t.error||"删除失败")}catch(t){console.error("删除机器人数据失败:",t),T("删除失败: "+((t==null?void 0:t.message)||String(t)),"error")}J()}async function Pt(e){try{const t=await P("delete-channel-data",{selfId:g.value,channelId:e});if(t.success){const a=`${g.value}:${e}`;delete u.value.messages[a],delete q.value[a],u.value.channels[g.value]&&delete u.value.channels[g.value][e],await je(a),$.value===e&&($.value=""),T(t.message||"已删除该频道的所有数据","success")}else throw new Error(t.error||"删除失败")}catch(t){console.error("删除频道数据失败:",t),T("删除失败: "+((t==null?void 0:t.message)||String(t)),"error")}J()}async function jt(e){$.value=e,ne.value=false,L.value&&(V.value="messages"),g.value&&await It(g.value,e),Ie(()=>{ve(),!L.value&&he.value&&he.value.focus()})}async function Nt(){if(!lt.value)return;const e=Se.value.trim();if(!e&&Y.value.length===0)return;me.value=true;const t=[...Y.value];try{const a=await P("send-message",{selfId:g.value,channelId:$.value,content:e,images:t.map(n=>({tempId:n.tempId,filename:n.filename}))});if(a.success){if(Se.value="",t.forEach(n=>{URL.revokeObjectURL(n.preview)}),Y.value=[],de.value=false,a.tempImageIds&&a.tempImageIds.length>0)try{await P("cleanup-temp-images",{tempImageIds:a.tempImageIds}),console.log("临时图片清理完成:",a.tempImageIds)}catch(n){console.warn("清理临时图片失败:",n)}}else console.error("消息发送失败:",a.error),T("发送失败: "+a.error,"error")}catch(a){console.error("发送消息时出错:",a),T("发送失败: "+((a==null?void 0:a.message)||String(a)),"error")}finally{me.value=false}}function Rt(){de.value=!de.value}function Ot(){Le.value&&Le.value.click(),de.value=false}async function Ft(e){const t=e.target,a=t.files;if(!(!a||a.length===0)){for(const n of Array.from(a))await Qe(n);t.value=""}}async function Ht(e){var a;const t=(a=e.clipboardData)==null?void 0:a.items;if(t){for(const n of Array.from(t))if(n.type.startsWith("image/")){e.preventDefault();const o=n.getAsFile();o&&await Qe(o)}}}async function Qe(e){try{if(e.size>10*1024*1024){T("图片文件过大,请选择小于10MB的图片","error");return}if(!e.type.startsWith("image/")){T("请选择图片文件","error");return}const t=await ut(e),a=URL.createObjectURL(e),n=await P("upload-image",{file:t,filename:e.name,mimeType:e.type});n.success?Y.value.push({tempId:n.tempId,filename:e.name,preview:a,size:e.size}):(URL.revokeObjectURL(a),T("图片上传失败: "+n.error,"error"))}catch(t){console.error("上传图片失败:",t),T("图片上传失败: "+((t==null?void 0:t.message)||String(t)),"error")}}async function Xt(e){try{const t=Y.value.findIndex(a=>a.tempId===e);if(t!==-1){const a=Y.value[t];URL.revokeObjectURL(a.preview),Y.value.splice(t,1)}await P("delete-temp-image",{tempId:e})}catch(t){console.error("删除图片失败:",t)}}function ut(e){return new Promise((t,a)=>{const n=new FileReader;n.onload=()=>t(n.result),n.onerror=a,n.readAsDataURL(e)})}function Ee(e){const t=e.target;t.closest(".input-actions")||(de.value=false),t.closest(".context-menu")||J()}function Yt(e){return new Date(e).toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit"})}function Vt(e){if(typeof e=="number")switch(e){case 0:return"文本";case 1:return"私聊";default:return"未知"}return String(e)}function ve(){B.value&&(B.value.scrollTop=B.value.scrollHeight,$e.value=false,ne.value=false)}function Ke(){if(B.value){const{scrollTop:e,scrollHeight:t,clientHeight:a}=B.value,o=t-(e+a)<=50,s=!o;$e.value=s,o?ne.value=false:ne.value=true}}function Me(){if(!B.value)return true;const{scrollTop:e,scrollHeight:t,clientHeight:a}=B.value;return t-(e+a)<=200}function dt(e){var n;if(!g.value)return 0;const t=`${g.value}:${e}`,a=q.value[t];return a!==void 0?a:((n=u.value.messages[t])==null?void 0:n.length)||0}function Wt(e,t){e.preventDefault(),e.stopPropagation();const a="touches"in e?e.touches[0].clientX:e.clientX,n="touches"in e?e.touches[0].clientY:e.clientY;qe.value=Date.now(),M.value={x:a,y:n},A.value={x:a,y:n},Z.value=false;const s=e.target.getBoundingClientRect();_e.value={x:s.left,y:s.top},pe.value={x:a-s.left,y:n-s.top},j.value=window.setTimeout(()=>{if(qe.value>0){Z.value=true,se.value=t;const i=e.target,c=i.cloneNode(true);c.classList.add("dragging-clone"),c.style.position="fixed",c.style.zIndex="1000",c.style.pointerEvents="none";const d=i.getBoundingClientRect();c.style.left=`${d.left}px`,c.style.top=`${d.top}px`,c.style.width=`${d.width}px`,c.style.height=`${d.height}px`,document.body.appendChild(c),C.value=c,document.body.style.userSelect="none",document.body.style.cursor="grabbing",document.body.classList.add("dragging-bubble-global"),ht(M.value.x,M.value.y)}},60),document.addEventListener("mousemove",Ae),document.addEventListener("mouseup",ze),document.addEventListener("touchmove",Ae),document.addEventListener("touchend",ze)}function Ae(e){if(!Z.value||!C.value)return;e.preventDefault();const t="touches"in e?e.touches[0].clientX:e.clientX,a="touches"in e?e.touches[0].clientY:e.clientY;A.value={x:t,y:a};const n=A.value.x-M.value.x,o=A.value.y-M.value.y,s=Math.sqrt(n*n+o*o),i=Math.max(.3,1-s/(H*2)),c=Math.max(.8,1-s/(H*3)),d=s>H,p=A.value.x-pe.value.x,k=A.value.y-pe.value.y;C.value.style.left=`${p}px`,C.value.style.top=`${k}px`,C.value.style.transform=`scale(${c})`,C.value.style.opacity=`${i}`,C.value.style.backgroundColor=d?"#f44336":"#2196f3",C.value.style.boxShadow=d?"0 4px 12px rgba(244, 67, 54, 0.4)":"0 4px 12px rgba(33, 150, 243, 0.4)",d?C.value.classList.add("will-delete"):C.value.classList.remove("will-delete")}function ze(e){if(j.value&&(clearTimeout(j.value),j.value=null),j.value&&(clearTimeout(j.value),j.value=null),!Z.value||!se.value){Pe();return}const t=se.value;if(Math.sqrt(Math.pow(A.value.x-M.value.x,2)+Math.pow(A.value.y-M.value.y,2))>H)ft(t),Pe();else if(C.value){C.value.style.transition="all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)";const n=document.querySelector(`[data-channel-id="${t}"] .channel-message-count`);if(n){const o=n.getBoundingClientRect();C.value.style.left=`${o.left}px`,C.value.style.top=`${o.top}px`,C.value.style.transform="scale(1)",C.value.style.opacity="1",C.value.style.backgroundColor="#2196f3",C.value.style.boxShadow="0 4px 12px rgba(33, 150, 243, 0.4)"}setTimeout(()=>{Pe()},300)}else Pe()}function Pe(){j.value&&(clearTimeout(j.value),j.value=null),se.value="",M.value={x:0,y:0},A.value={x:0,y:0},_e.value={x:0,y:0},qe.value=0,Z.value=false,document.removeEventListener("mousemove",Ae),document.removeEventListener("mouseup",ze),document.removeEventListener("touchmove",Ae),document.removeEventListener("touchend",ze),document.body.style.userSelect="",document.body.style.cursor="",document.body.classList.remove("dragging-bubble-global"),C.value&&C.value.parentNode&&(C.value.parentNode.removeChild(C.value),C.value=null),mt()}function Jt(e){return se.value===e&&Z.value?{visibility:"hidden",pointerEvents:"none",transition:"none"}:{}}function Gt(e){if(se.value!==e)return 0;const t=A.value.x-M.value.x,a=A.value.y-M.value.y;return Math.sqrt(t*t+a*a)}async function ft(e){if(g.value)try{const t=`${g.value}:${e}`,a=dt(e),n=ce.value.keepMessagesOnClear;if(n>0&&a<=n){T("当前消息还很少诶~ 无需清理","success");return}const o=await P("clear-channel-history",{selfId:g.value,channelId:e});if(o.success)if(o.clearedCount&&o.clearedCount>0){if(u.value.messages[t]){const i=[...u.value.messages[t]].sort((c,d)=>c.timestamp-d.timestamp);u.value.messages[t]=i.slice(-o.keptCount)}q.value[t]=o.keptCount,await je(t),T(`历史记录已清理,清理了 ${o.clearedCount} 条消息,保留最新 ${o.keptCount} 条`,"success")}else n===0?(u.value.messages[t]&&(u.value.messages[t]=[]),q.value[t]=0,await je(t),T("历史记录已清理,所有消息已删除","success")):T("当前消息还很少诶~ 无需清理","success");else console.error("清理历史记录失败:",o.error),T("清理失败: "+o.error,"error")}catch(t){console.error("清理历史记录时出错:",t),T("清理失败: "+((t==null?void 0:t.message)||String(t)),"error")}}function T(e,t="success"){const a=document.createElement("div");a.className=`notification ${t}`,a.textContent=e;let n="#4caf50";switch(t){case"info":n="#2196f3";break;case"warn":n="#ff9800";break;case"error":n="#f44336";break;case"success":n="#4caf50";break}a.style.cssText=`
1
+ import{defineComponent as Ce,ref as v,onMounted as st,h,computed as E,watch as St,nextTick as ye,onUnmounted as ga,createElementBlock as x,openBlock as y,unref as r,normalizeStyle as ot,normalizeClass as le,createCommentVNode as B,createElementVNode as f,Fragment as ee,renderList as _e,createBlock as Re,toDisplayString as _,withDirectives as Bt,createTextVNode as rt,vShow as ya,withModifiers as $t,withKeys as pa,isRef as wa,vModelText as Ia,resolveComponent as xa}from"vue";import{receive as lt,send as P,icons as Ca}from"@koishijs/client";function ka(){function te(e){try{return new URL(e).protocol==="file:"}catch{return false}}const ce=Ce({props:{src:{type:String,required:true},alt:{type:String,default:"头像"},channelKey:{type:String,required:true}},setup(e){const t=v("loading"),a=v(e.src),n=v(""),o=async()=>{try{t.value="loading";const i=await Ve(e.channelKey,e.src);if(i){a.value=i,t.value="loaded";return}const c=new Image;c.crossOrigin="anonymous",c.referrerPolicy="no-referrer",c.draggable=false;const d=new Promise((k,w)=>{c.onload=()=>k(),c.onerror=()=>w(new Error("Direct load failed")),c.src=e.src}),p=new Promise((k,w)=>{setTimeout(()=>w(new Error("Timeout")),3e3)});try{await Promise.race([d,p]),a.value=e.src,t.value="loaded",xe(e.channelKey,e.src).catch(k=>{console.warn("异步缓存头像失败:",k)})}catch{await s()}}catch(i){console.error("头像加载失败:",i),t.value="error",n.value="头像加载失败"}},s=async()=>{try{t.value="caching";const i=await xe(e.channelKey,e.src);if(i)a.value=i,t.value="loaded";else throw new Error("缓存系统加载失败")}catch(i){console.error("缓存系统加载头像失败:",i),t.value="error",n.value=(i==null?void 0:i.message)||"缓存加载失败"}};return st(()=>{o()}),()=>{switch(t.value){case"loading":case"caching":return h("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase());case"loaded":return h("img",{src:a.value,alt:e.alt,draggable:false,style:{width:"100%",height:"100%","object-fit":"cover"}});case"error":return h("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase());default:return h("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase())}}}}),Y=Ce({props:{src:{type:String,required:true},alt:{type:String,default:"图片"},filename:{type:String,default:""},channelKey:{type:String,required:true}},setup(e){const t=v("loading"),a=v(e.src),n=v(""),o=v(null),s=async()=>{try{t.value="loading";const c=await Ve(e.channelKey,e.src);if(c){a.value=c,t.value="loaded";return}if(te(e.src)){console.log("ImageComponent: 检测到本地文件,使用代理请求:",e.src),await i();return}const d=new Image;d.crossOrigin="anonymous",d.referrerPolicy="no-referrer",d.draggable=false;const p=new Promise((w,O)=>{d.onload=()=>w(),d.onerror=()=>O(new Error("Direct load failed")),d.src=e.src}),k=new Promise((w,O)=>{setTimeout(()=>O(new Error("Timeout")),3e3)});try{await Promise.race([p,k]),a.value=e.src,t.value="loaded",xe(e.channelKey,e.src).catch(w=>{console.warn("异步缓存图片失败:",w)})}catch{await i()}}catch(c){console.error("图片加载失败:",c),t.value="error",n.value="图片加载失败"}},i=async()=>{try{t.value="caching";const c=await xe(e.channelKey,e.src);if(c)a.value=c,t.value="loaded";else throw new Error("缓存系统加载失败")}catch(c){console.error("缓存系统加载图片失败:",c),t.value="error",n.value=(c==null?void 0:c.message)||"缓存加载失败"}};return st(()=>{s()}),()=>{switch(t.value){case"loading":return h("div",{class:"message-image-loading"},"加载中...");case"caching":return h("div",{class:"message-image-loading"},"[图片加载缓存中...]");case"loaded":return h("img",{src:a.value,alt:e.alt,class:"message-image",loading:"lazy",ref:o,draggable:false,style:{"max-width":"min(400px, 66.67vw)","max-height":"200px",width:"auto",height:"auto","object-fit":"contain"},onLoad:()=>{o.value&&e.src.toLowerCase().includes(".gif")&&(o.value.style.imageRendering="auto")}});case"error":return h("div",{class:"message-image-error"},["图片加载失败",h("br"),h("small",e.filename||e.alt||"未知图片"),h("br"),h("small",{style:"color: #ff9800;"},n.value)]);default:return h("div",{class:"message-image-error"},"未知状态")}}}}),pe=Ce({props:{data:{type:String,required:true},channelKey:{type:String,required:true}},setup(e){const a=(()=>{try{const o=JSON.parse(e.data);if(o.meta&&o.meta.detail_1){const s=o.meta.detail_1;return{type:"share_card",title:s.title||o.prompt||"分享内容",desc:s.desc||"",preview:s.preview?s.preview.replace(/\\\//g,"/"):"",icon:s.icon?s.icon.replace(/\\\//g,"/"):"",url:s.qqdocurl?s.qqdocurl.replace(/\\\//g,"/"):s.url?s.url.replace(/\\\//g,"/"):"",appName:s.title||"应用"}}return{type:"raw",data:o}}catch(o){return console.error("解析JSON数据失败:",o),{type:"error",error:"无法解析的JSON数据"}}})(),n=()=>{a.type==="share_card"&&a.url&&window.open(a.url,"_blank","noopener,noreferrer")};return()=>a.type==="share_card"&&a.preview?h("img",{src:a.preview,alt:a.title||"[分享小程序]",class:"message-image",loading:"lazy",draggable:false,onClick:n,style:{"max-width":"400px","max-height":"200px",width:"auto",height:"auto","object-fit":"contain",cursor:a.url?"pointer":"default"},title:a.url?`点击打开: ${a.title||"链接"}`:a.title,onError:o=>{const i=o.target.parentElement;i&&(i.style.display="none")}}):a.type==="error"?h("div",{class:"message-json-error"},[h("span",{class:"json-error-text"},a.error),h("details",{class:"json-raw-data"},[h("summary","查看原始数据"),h("pre",{class:"json-raw-content"},e.data)])]):h("div",{class:"message-json-raw"},[h("div",{class:"json-label"},"[JSON数据]"),h("details",{class:"json-raw-data"},[h("summary","查看详情"),h("pre",{class:"json-raw-content"},JSON.stringify(a.data,null,2))])])}}),Z=Ce({props:{element:{type:Object,required:true},channelKey:{type:String,required:true}},setup(e){const t=v(false),a=()=>{t.value=!t.value},n=()=>{if(!e.element.children||e.element.children.length===0)return{previews:[],messageCount:0};const s=e.element.children.filter(d=>d.type==="message"),i=s.length;return{previews:s.slice(0,3).map(d=>{var w,O;const p=((w=d.attrs)==null?void 0:w.nickname)||"用户";let k="";if(d.children&&d.children.length>0){const z=d.children[0];z.type==="text"?(k=(((O=z.attrs)==null?void 0:O.content)||"").substring(0,20),k.length>15&&(k+="...")):z.type==="img"?k="[图片]":z.type==="video"?k="[视频]":k=`[${z.type}]`}return`${p}:${k}`}),messageCount:i}},o=(s,i)=>{var p,k,w;const c=((p=s.attrs)==null?void 0:p.nickname)||"用户",d=((k=s.attrs)==null?void 0:k.userId)||"unknown";return h("div",{key:i,class:"forwarded-message-item"},[h("div",{class:"forwarded-message-header"},[h("span",{class:"forwarded-message-nickname"},c),h("span",{class:"forwarded-message-userid"},`(${d})`)]),h("div",{class:"forwarded-message-content"},((w=s.children)==null?void 0:w.map((O,z)=>h(ke,{key:z,element:O,channelKey:e.channelKey})))||[])])};return()=>{var c;const{previews:s,messageCount:i}=n();return h("div",{class:"forward-message-container"},[h("div",{class:"forward-message-preview",onClick:a},[h("div",{class:"forward-message-title"},"聊天记录"),...s.map((d,p)=>h("div",{key:p,class:"forward-message-preview-item"},d)),h("div",{class:"forward-message-footer"},[h("span",{class:"forward-message-count"},`查看${i}条转发消息`),h("span",{class:"forward-message-toggle"},t.value?"▲":"▼")])]),t.value&&h("div",{class:"forward-message-expanded"},((c=e.element.children)==null?void 0:c.filter(d=>d.type==="message").map((d,p)=>o(d,p)))||[])])}}}),ke=Ce({props:{element:{type:Object,required:true},channelKey:{type:String,required:true}},setup(e){const t=a=>{var n,o,s,i,c,d;switch(a.type){case"text":return h("span",{class:"message-text-content"},a.attrs.content||"");case"forward":return h("span",{class:"message-text-content"},`[转发消息 ${a.attrs.id}]`||"[转发消息]");case"img":case"image":const p=a.attrs.src||a.attrs.url||a.attrs.file;return h("div",{class:"message-image-container"},[h(Y,{src:p,alt:a.attrs.summary||"图片",filename:a.attrs.filename||a.attrs.summary||"",channelKey:e.channelKey})]);case"mface":const k=a.attrs.src||a.attrs.url||a.attrs.file;return h("div",{class:"message-image-container"},[h(Y,{src:k,alt:a.attrs.summary||"表情",filename:a.attrs.emojiId||a.attrs.summary||"",channelKey:e.channelKey})]);case"face":if((o=(n=a.children[0])==null?void 0:n.attrs)!=null&&o.src){const w=((i=(s=a.children[0])==null?void 0:s.attrs)==null?void 0:i.src)||((d=(c=a.children[0])==null?void 0:c.attrs)==null?void 0:d.url);return h("div",{class:"message-image-container"},[h(Y,{src:w,alt:a.attrs.name||a.attrs.id||"[表情]",filename:a.attrs.name||a.attrs.id||"[表情]",channelKey:e.channelKey})])}else return h("span",{class:"message-text-content"},`[${a.attrs.name||a.attrs.id}]`||"[表情]");case"at":return h("span",{class:"message-at",title:a.attrs.name},`${a.attrs.name||a.attrs.id}`);case"json":return h("div",{class:"message-image-container"},[h(pe,{data:a.attrs.data||"",channelKey:e.channelKey})]);case"p":if(a.children&&a.children.length>0){const w=a.children.map((O,z)=>h(ke,{key:z,element:O,channelKey:e.channelKey}));return h("div",{class:"message-paragraph"},w)}else return h("div",{class:"message-paragraph"},"");case"figure":return h(Z,{element:a,channelKey:e.channelKey});default:return h("span",{class:"message-unknown",title:`未知消息类型: ${a.type}`},a.attrs.content||`[${a.type}]`)}};return()=>t(e.element)}}),u=v({bots:{},channels:{},messages:{}}),U=v({}),ie=v({maxMessagesPerChannel:1e3,keepMessagesOnClear:50,loggerinfo:false,blockedPlatforms:[],chatContainerHeight:80}),b=v({}),be=100*1024*1024,ue=50;let we=0,I=null;const Ne="ChatImageCache",Oe=2,$="images",ae=50*1024*1024,M=100,de=500,Le=2*1024*1024,Fe=.8,We=60*1e3;let F=0,K=0,He=0;const g=v(""),S=v(""),Se=v(""),V=v([]),fe=v(false),Te=v(),q=v(false),W=v("bots"),H=v(null),ne=v(null),Be=v(false),he=v({show:false,text:""}),D=v(),me=v(),$e=v(false),se=v(false),ve=v(false),oe=v(""),j=v({x:0,y:0}),A=v({x:0,y:0}),De=v({x:0,y:0}),Ie=v({x:0,y:0}),X=80,qe=v(0),R=v(null),Q=v(false),C=v(null),N=v({show:false,x:0,y:0,type:null,targetId:"",isSecondClick:false}),J=v(new Set),re=v(new Set),m=E(()=>Object.values(u.value.bots).sort((t,a)=>{const n=J.value.has(t.selfId),o=J.value.has(a.selfId);return n&&!o?-1:!n&&o?1:0})),l=E(()=>!g.value||!u.value.channels[g.value]?[]:Object.values(u.value.channels[g.value]).sort((t,a)=>{const n=re.value.has(`${g.value}:${t.id}`),o=re.value.has(`${g.value}:${a.id}`);return n&&!o?-1:!n&&o?1:0})),L=E(()=>{if(!g.value||!S.value)return[];const e=`${g.value}:${S.value}`,t=u.value.messages[e]||[];return t.filter(a=>a.quote),t}),Ue=E(()=>{var t;if(!g.value||!S.value)return"";const e=u.value.channels[g.value];return((t=e==null?void 0:e[S.value])==null?void 0:t.name)||""}),_t=E(()=>!g.value||!S.value?"":`${g.value}:${S.value}`),ct=E(()=>g.value&&S.value&&(Se.value.trim()||V.value.length>0)&&!ve.value),Lt=E(()=>g.value&&S.value&&!ve.value),Tt=E(()=>{if(!q.value)return"";switch(W.value){case"channels":return"show-channels";case"messages":return"show-messages";default:return""}}),qt=E(()=>q.value?"输入消息...(屏幕左滑返回)":"输入消息..."),Ut=E(()=>({}));function it(e){return e.size||0}function Xe(e){we+=e,ie.value.loggerinfo&&console.log(`内存使用量变化: ${e>0?"+":""}${(e/1024/1024).toFixed(2)}MB, 总计: ${(we/1024/1024).toFixed(2)}MB`)}function ut(e=10){const t=Object.entries(b.value);if(t.length<=e)return;const a=t.slice(0,t.length-e);let n=0;a.forEach(([o,s])=>{URL.revokeObjectURL(s),delete b.value[o],n+=500*1024,ie.value.loggerinfo&&console.log("清理旧blob URL:",o)}),Xe(-n)}function Je(){Object.keys(b.value).length>ue&&ut(Math.floor(ue*.7)),we>be&&ut(Math.floor(ue*.5))}function Mt(e){g.value=e,S.value="",at(),q.value&&(W.value="channels")}function Kt(e,t){if(e.preventDefault(),e.stopPropagation(),N.value.show&&N.value.type==="bot"&&N.value.targetId===t){G();return}Ge(e,"bot",t)}function jt(e,t){if(e.preventDefault(),e.stopPropagation(),N.value.show&&N.value.type==="channel"&&N.value.targetId===t){G();return}Ge(e,"channel",t)}function Ge(e,t,a){let s=e.clientX,i=e.clientY;s+180>window.innerWidth&&(s=window.innerWidth-180-10),i+80>window.innerHeight&&(i=window.innerHeight-80-10),N.value={show:true,x:s,y:i,type:t,targetId:a,isSecondClick:false},document.addEventListener("click",G,{once:true}),document.addEventListener("keydown",Ze)}function G(){N.value.show=false,document.removeEventListener("click",G),document.removeEventListener("keydown",Ze)}function Ze(e){e.key==="Escape"&&N.value.show&&G()}async function At(e){J.value.has(e)?J.value.delete(e):J.value.add(e),await P("set-pinned-bots",{pinnedBots:Array.from(J.value)}),G()}async function zt(e){const t=`${g.value}:${e}`;re.value.has(t)?re.value.delete(t):re.value.add(t),await P("set-pinned-channels",{pinnedChannels:Array.from(re.value)}),G()}async function Pt(e){try{const t=await P("delete-bot-data",{selfId:e});if(t.success){const a=Object.keys(u.value.messages).filter(n=>n.startsWith(`${e}:`));for(const n of a)delete u.value.messages[n],delete U.value[n],await Pe(n);delete u.value.bots[e],delete u.value.channels[e],g.value===e&&(g.value="",S.value=""),T(t.message||"已删除该机器人的所有数据","success")}else throw new Error(t.error||"删除失败")}catch(t){console.error("删除机器人数据失败:",t),T("删除失败: "+((t==null?void 0:t.message)||String(t)),"error")}G()}async function Rt(e){try{const t=await P("delete-channel-data",{selfId:g.value,channelId:e});if(t.success){const a=`${g.value}:${e}`;delete u.value.messages[a],delete U.value[a],u.value.channels[g.value]&&delete u.value.channels[g.value][e],await Pe(a),S.value===e&&(S.value=""),T(t.message||"已删除该频道的所有数据","success")}else throw new Error(t.error||"删除失败")}catch(t){console.error("删除频道数据失败:",t),T("删除失败: "+((t==null?void 0:t.message)||String(t)),"error")}G()}async function Nt(e){S.value=e,se.value=false,at(),q.value&&(W.value="messages"),g.value&&await Ct(g.value,e),ye(()=>{ge(),!q.value&&me.value&&me.value.focus()})}async function Ot(){if(!ct.value)return;const e=Se.value.trim();if(!e&&V.value.length===0)return;ve.value=true;const t=[...V.value];try{const a=await P("send-message",{selfId:g.value,channelId:S.value,content:e,images:t.map(n=>({tempId:n.tempId,filename:n.filename}))});if(a.success){if(Se.value="",t.forEach(n=>{URL.revokeObjectURL(n.preview)}),V.value=[],fe.value=false,a.tempImageIds&&a.tempImageIds.length>0)try{await P("cleanup-temp-images",{tempImageIds:a.tempImageIds}),console.log("临时图片清理完成:",a.tempImageIds)}catch(n){console.warn("清理临时图片失败:",n)}}else console.error("消息发送失败:",a.error),T("发送失败: "+a.error,"error")}catch(a){console.error("发送消息时出错:",a),T("发送失败: "+((a==null?void 0:a.message)||String(a)),"error")}finally{ve.value=false}}function Ft(){fe.value=!fe.value}function Ht(){Te.value&&Te.value.click(),fe.value=false}async function Xt(e){const t=e.target,a=t.files;if(!(!a||a.length===0)){for(const n of Array.from(a))await Qe(n);t.value=""}}async function Yt(e){var a;const t=(a=e.clipboardData)==null?void 0:a.items;if(t){for(const n of Array.from(t))if(n.type.startsWith("image/")){e.preventDefault();const o=n.getAsFile();if(o){const s=n.type==="image/gif"?".gif":n.type==="image/png"?".png":(n.type==="image/jpeg",".jpg"),i=`pasted-image-${Date.now()}${s}`,c=new File([o],i,{type:n.type,lastModified:Date.now()});await Qe(c)}}}}async function Qe(e){try{if(e.size>10*1024*1024){T("图片文件过大,请选择小于10MB的图片","error");return}if(!e.type.startsWith("image/")){T("请选择图片文件","error");return}const t=await dt(e),a=URL.createObjectURL(e),n=await P("upload-image",{file:t,filename:e.name,mimeType:e.type,isGif:e.type==="image/gif"});n.success?V.value.push({tempId:n.tempId,filename:e.name,preview:a,size:e.size}):(URL.revokeObjectURL(a),T("图片上传失败: "+n.error,"error"))}catch(t){console.error("上传图片失败:",t),T("图片上传失败: "+((t==null?void 0:t.message)||String(t)),"error")}}async function Vt(e){try{const t=V.value.findIndex(a=>a.tempId===e);if(t!==-1){const a=V.value[t];URL.revokeObjectURL(a.preview),V.value.splice(t,1)}await P("delete-temp-image",{tempId:e})}catch(t){console.error("删除图片失败:",t)}}function dt(e){return new Promise((t,a)=>{const n=new FileReader;n.onload=()=>t(n.result),n.onerror=a,n.readAsDataURL(e)})}function Ee(e){const t=e.target;t.closest(".input-actions")||(fe.value=false),t.closest(".context-menu")||G()}function Wt(e){return new Date(e).toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit"})}function Jt(e){if(typeof e=="number")switch(e){case 0:return"文本";case 1:return"私聊";default:return"未知"}return String(e)}function ge(){D.value&&(D.value.scrollTop=D.value.scrollHeight,$e.value=false,se.value=false)}function Me(){if(D.value){const{scrollTop:e,scrollHeight:t,clientHeight:a}=D.value,o=t-(e+a)<=50,s=!o;$e.value=s,o?se.value=false:se.value=true}}function Ke(){if(!D.value)return true;const{scrollTop:e,scrollHeight:t,clientHeight:a}=D.value;return t-(e+a)<=200}function ft(e){var n;if(!g.value)return 0;const t=`${g.value}:${e}`,a=U.value[t];return a!==void 0?a:((n=u.value.messages[t])==null?void 0:n.length)||0}function Gt(e,t){e.preventDefault(),e.stopPropagation();const a="touches"in e?e.touches[0].clientX:e.clientX,n="touches"in e?e.touches[0].clientY:e.clientY;qe.value=Date.now(),j.value={x:a,y:n},A.value={x:a,y:n},Q.value=false;const s=e.target.getBoundingClientRect();De.value={x:s.left,y:s.top},Ie.value={x:a-s.left,y:n-s.top},R.value=window.setTimeout(()=>{if(qe.value>0){Q.value=true,oe.value=t;const i=e.target,c=i.cloneNode(true);c.classList.add("dragging-clone"),c.style.position="fixed",c.style.zIndex="1000",c.style.pointerEvents="none";const d=i.getBoundingClientRect();c.style.left=`${d.left}px`,c.style.top=`${d.top}px`,c.style.width=`${d.width}px`,c.style.height=`${d.height}px`,document.body.appendChild(c),C.value=c,document.body.style.userSelect="none",document.body.style.cursor="grabbing",document.body.classList.add("dragging-bubble-global"),mt(j.value.x,j.value.y)}},60),document.addEventListener("mousemove",je),document.addEventListener("mouseup",Ae),document.addEventListener("touchmove",je),document.addEventListener("touchend",Ae)}function je(e){if(!Q.value||!C.value)return;e.preventDefault();const t="touches"in e?e.touches[0].clientX:e.clientX,a="touches"in e?e.touches[0].clientY:e.clientY;A.value={x:t,y:a};const n=A.value.x-j.value.x,o=A.value.y-j.value.y,s=Math.sqrt(n*n+o*o),i=Math.max(.3,1-s/(X*2)),c=Math.max(.8,1-s/(X*3)),d=s>X,p=A.value.x-Ie.value.x,k=A.value.y-Ie.value.y;C.value.style.left=`${p}px`,C.value.style.top=`${k}px`,C.value.style.transform=`scale(${c})`,C.value.style.opacity=`${i}`,C.value.style.backgroundColor=d?"#f44336":"#2196f3",C.value.style.boxShadow=d?"0 4px 12px rgba(244, 67, 54, 0.4)":"0 4px 12px rgba(33, 150, 243, 0.4)",d?C.value.classList.add("will-delete"):C.value.classList.remove("will-delete")}function Ae(e){if(R.value&&(clearTimeout(R.value),R.value=null),R.value&&(clearTimeout(R.value),R.value=null),!Q.value||!oe.value){ze();return}const t=oe.value;if(Math.sqrt(Math.pow(A.value.x-j.value.x,2)+Math.pow(A.value.y-j.value.y,2))>X)ht(t),ze();else if(C.value){C.value.style.transition="all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)";const n=document.querySelector(`[data-channel-id="${t}"] .channel-message-count`);if(n){const o=n.getBoundingClientRect();C.value.style.left=`${o.left}px`,C.value.style.top=`${o.top}px`,C.value.style.transform="scale(1)",C.value.style.opacity="1",C.value.style.backgroundColor="#2196f3",C.value.style.boxShadow="0 4px 12px rgba(33, 150, 243, 0.4)"}setTimeout(()=>{ze()},300)}else ze()}function ze(){R.value&&(clearTimeout(R.value),R.value=null),oe.value="",j.value={x:0,y:0},A.value={x:0,y:0},De.value={x:0,y:0},qe.value=0,Q.value=false,document.removeEventListener("mousemove",je),document.removeEventListener("mouseup",Ae),document.removeEventListener("touchmove",je),document.removeEventListener("touchend",Ae),document.body.style.userSelect="",document.body.style.cursor="",document.body.classList.remove("dragging-bubble-global"),C.value&&C.value.parentNode&&(C.value.parentNode.removeChild(C.value),C.value=null),vt()}function Zt(e){return oe.value===e&&Q.value?{visibility:"hidden",pointerEvents:"none",transition:"none"}:{}}function Qt(e){if(oe.value!==e)return 0;const t=A.value.x-j.value.x,a=A.value.y-j.value.y;return Math.sqrt(t*t+a*a)}async function ht(e){if(g.value)try{const t=`${g.value}:${e}`,a=ft(e),n=ie.value.keepMessagesOnClear;if(n>0&&a<=n){T("当前消息还很少诶~ 无需清理","success");return}const o=await P("clear-channel-history",{selfId:g.value,channelId:e});if(o.success)if(o.clearedCount&&o.clearedCount>0){if(u.value.messages[t]){const i=[...u.value.messages[t]].sort((c,d)=>c.timestamp-d.timestamp);u.value.messages[t]=i.slice(-o.keptCount)}U.value[t]=o.keptCount,await Pe(t),T(`历史记录已清理,清理了 ${o.clearedCount} 条消息,保留最新 ${o.keptCount} 条`,"success")}else n===0?(u.value.messages[t]&&(u.value.messages[t]=[]),U.value[t]=0,await Pe(t),T("历史记录已清理,所有消息已删除","success")):T("当前消息还很少诶~ 无需清理","success");else console.error("清理历史记录失败:",o.error),T("清理失败: "+o.error,"error")}catch(t){console.error("清理历史记录时出错:",t),T("清理失败: "+((t==null?void 0:t.message)||String(t)),"error")}}function T(e,t="success"){const a=document.createElement("div");a.className=`notification ${t}`,a.textContent=e;let n="#4caf50";switch(t){case"info":n="#2196f3";break;case"warn":n="#ff9800";break;case"error":n="#f44336";break;case"success":n="#4caf50";break}a.style.cssText=`
2
2
  position: fixed;
3
3
  top: 20px;
4
4
  right: 20px;
@@ -19,9 +19,9 @@ import{defineComponent as Ce,ref as v,onMounted as nt,h,computed as Q,watch as k
19
19
  from { transform: translateX(0); opacity: 1; }
20
20
  to { transform: translateX(100%); opacity: 0; }
21
21
  }
22
- `,document.head.appendChild(o),document.body.appendChild(a),setTimeout(()=>{a.style.animation="slideOut 0.3s ease-in",setTimeout(()=>{a.parentNode&&a.parentNode.removeChild(a),o.parentNode&&o.parentNode.removeChild(o)},300)},3e3)}function ht(e,t){const a=document.createElement("div");a.className="drag-threshold-circle",a.style.cssText=`
23
- left: ${e-H}px;
24
- top: ${t-H}px;
25
- width: ${H*2}px;
26
- height: ${H*2}px;
27
- `,document.body.appendChild(a),window.dragThresholdCircle=a}function mt(){const e=window.dragThresholdCircle;e&&e.parentNode&&(e.parentNode.removeChild(e),window.dragThresholdCircle=null)}async function et(){try{if(!I)return false;const e=Date.now();if(e-He<We)return true;He=e;const t=await vt();O=t.totalSize,K=t.totalImages,console.log("数据库健康检查:",{大小:`${(O/1024/1024).toFixed(2)}MB / ${(te/1024/1024).toFixed(2)}MB`,图片数量:`${K} / ${ue}`,使用率:`${(O/te*100).toFixed(1)}%`});const a=O/te,n=K/ue;return(a>Fe||n>Fe)&&(console.warn("数据库使用率过高,开始自动清理"),await Ye()),(a>.95||n>.95)&&(console.error("数据库接近极限,执行紧急清理"),await Zt()),true}catch(e){return console.error("数据库健康检查失败:",e),false}}async function vt(){return I?new Promise(e=>{const n=I.transaction([S],"readonly").objectStore(S).getAll();n.onsuccess=()=>{const o=n.result||[];let s=0;const i={};o.forEach(c=>{s+=c.size||0,i[c.channelKey]=(i[c.channelKey]||0)+1}),e({totalSize:s,totalImages:o.length,channelStats:i})},n.onerror=()=>{console.error("获取数据库统计失败:",n.error),e({totalSize:0,totalImages:0,channelStats:{}})}}):{totalSize:0,totalImages:0,channelStats:{}}}async function Ye(){try{console.log("开始自动清理...");const e=await gt();if(e.length===0)return;const t={};e.forEach(o=>{t[o.channelKey]||(t[o.channelKey]=[]),t[o.channelKey].push(o)});let a=0,n=0;for(const[o,s]of Object.entries(t))if(s.length>U){s.sort((c,d)=>c.timestamp-d.timestamp);const i=s.slice(0,s.length-U);for(const c of i)await tt(c.url),a++,n+=c.size||0,b.value[c.url]&&(URL.revokeObjectURL(b.value[c.url]),delete b.value[c.url])}console.log(`自动清理完成: 清理了 ${a} 张图片,释放了 ${(n/1024/1024).toFixed(2)}MB`),K-=a,O-=n}catch(e){console.error("自动清理失败:",e)}}async function Zt(){try{console.log("开始紧急清理...");const e=await gt();if(e.length===0)return;e.sort((s,i)=>i.timestamp-s.timestamp);const t=Math.floor(ue*.3),a=e.slice(t);let n=0,o=0;for(const s of a)await tt(s.url),n++,o+=s.size||0,b.value[s.url]&&(URL.revokeObjectURL(b.value[s.url]),delete b.value[s.url]);console.log(`紧急清理完成: 清理了 ${n} 张图片,释放了 ${(o/1024/1024).toFixed(2)}MB`),K=t,O-=o}catch(e){console.error("紧急清理失败:",e)}}async function gt(){return I?new Promise(e=>{const n=I.transaction([S],"readonly").objectStore(S).getAll();n.onsuccess=()=>{e(n.result||[])},n.onerror=()=>{console.error("获取所有图片失败:",n.error),e([])}}):[]}async function Qt(){return new Promise(e=>{try{I&&(I.close(),I=null);const t=indexedDB.deleteDatabase(Re);t.onsuccess=()=>{console.log("IndexedDB数据库已完全清理"),O=0,K=0,e(true)},t.onerror=()=>{console.error("清理IndexedDB数据库失败:",t.error),e(false)},t.onblocked=()=>{console.warn("IndexedDB数据库删除被阻塞,可能有其他连接正在使用"),setTimeout(()=>{e(false)},5e3)}}catch(t){console.error("清理数据库时出错:",t),e(false)}})}async function Et(){try{return await yt()?(setTimeout(async()=>{const t=await vt();console.log("数据库初始状态:",{大小:`${(t.totalSize/1024/1024).toFixed(2)}MB`,图片数量:t.totalImages,频道分布:t.channelStats}),(t.totalSize>te*.9||t.totalImages>ue*.9)&&(console.warn("数据库初始状态接近限制,执行清理"),await Ye())},1e3),true):(console.warn("数据库打开失败,尝试清理后重新初始化"),await Qt(),await yt())}catch(e){return console.error("IndexedDB初始化出错:",e),false}}async function yt(){return new Promise(e=>{try{const t=indexedDB.open(Re,Oe);t.onerror=()=>{console.error("IndexedDB打开失败:",t.error),e(false)},t.onsuccess=()=>{I=t.result,I.onerror=a=>{console.error("IndexedDB运行时错误:",a)},I.onversionchange=()=>{console.warn("IndexedDB版本变更,关闭连接"),I==null||I.close(),I=null},e(true)},t.onupgradeneeded=a=>{const n=a.target.result;if(!n.objectStoreNames.contains(S)){const o=n.createObjectStore(S,{keyPath:"url"});o.createIndex("channelKey","channelKey",{unique:false}),o.createIndex("timestamp","timestamp",{unique:false}),o.createIndex("size","size",{unique:false}),console.log("IndexedDB对象存储创建完成")}},t.onblocked=()=>{console.warn("IndexedDB打开被阻塞"),e(false)}}catch(t){console.error("打开数据库时出错:",t),e(false)}})}async function ea(e){return I?new Promise((t,a)=>{const s=I.transaction([S],"readonly").objectStore(S).get(e);s.onsuccess=()=>{t(s.result||null)},s.onerror=()=>{console.error("从IndexedDB获取图片失败:",s.error),t(null)}}):null}async function pt(e){if(!I)return false;try{return e.size>Te?(console.warn(`图片过大,跳过缓存: ${(e.size/1024/1024).toFixed(2)}MB > ${(Te/1024/1024).toFixed(2)}MB`),false):(await et(),O+e.size>te&&(console.warn("添加图片会超过数据库大小限制,执行清理"),await Ye(),O+e.size>te)?(console.warn("清理后仍会超过限制,跳过此图片"),false):K>=ue&&(console.warn("图片数量已达上限,执行清理"),await Ye(),K>=ue)?(console.warn("清理后仍达上限,跳过此图片"),false):new Promise(t=>{const o=I.transaction([S],"readwrite").objectStore(S).put(e);o.onsuccess=()=>{O+=e.size,K+=1,t(true)},o.onerror=()=>{console.error("保存图片到IndexedDB失败:",o.error),t(false)}}))}catch(t){return console.error("保存图片时出错:",t),false}}async function tt(e){return I?new Promise(t=>{const o=I.transaction([S],"readwrite").objectStore(S).delete(e);o.onsuccess=()=>{t(true)},o.onerror=()=>{console.error("从IndexedDB删除图片失败:",o.error),t(false)}}):false}async function ta(e){return I?new Promise(t=>{const s=I.transaction([S],"readonly").objectStore(S).index("channelKey").getAll(e);s.onsuccess=()=>{t(s.result||[])},s.onerror=()=>{console.error("获取频道图片失败:",s.error),t([])}}):[]}async function Ve(e,t){const a=b.value[t];if(a)return a;const n=await ea(t);if(!n)return null;Je();const o=URL.createObjectURL(n.blob);return b.value[t]=o,Xe(ct(n.blob)),n.timestamp=Date.now(),await pt(n),o}async function we(e,t){try{const a=await Ve(e,t);if(a)return a;const n=await P("fetch-image",{url:t});if(!n.success)return console.error("获取图片失败:",n.error),null;const o=n.base64,s=n.contentType||"image/jpeg",i=atob(o),c=new Array(i.length);for(let z=0;z<i.length;z++)c[z]=i.charCodeAt(z);const d=new Uint8Array(c),p=new Blob([d],{type:s});if(p.size>Te)return console.warn(`图片过大,跳过缓存: ${(p.size/1024/1024).toFixed(2)}MB`),null;const k={url:t,blob:p,timestamp:Date.now(),size:p.size,channelKey:e};if(!await pt(k))return console.error("保存图片到IndexedDB失败"),null;Je();const R=URL.createObjectURL(p);return b.value[t]=R,Xe(ct(p)),R}catch(a){return console.error("缓存图片失败:",a),null}}async function je(e){try{const t=await ta(e);let a=0;for(const n of t)await tt(n.url),b.value[n.url]&&(URL.revokeObjectURL(b.value[n.url]),delete b.value[n.url],a+=n.size||0);a>0&&Xe(-a)}catch(t){console.error("清理频道图片缓存失败:",t)}}function aa(){const e=Object.keys(b.value).length;return{blobCount:e,estimatedMemoryUsage:ye,maxMemoryLimit:be,maxBlobLimit:ie,memoryUsagePercent:(ye/be*100).toFixed(1),blobUsagePercent:(e/ie*100).toFixed(1)}}async function na(){return I?new Promise(e=>{const n=I.transaction([S],"readonly").objectStore(S).getAll();n.onsuccess=()=>{const o=n.result||[],s=new Set;let i=0;o.forEach(c=>{s.add(c.channelKey),i+=c.size}),e({totalImages:o.length,totalSize:i,channels:s.size})},n.onerror=()=>{console.error("获取缓存统计失败:",n.error),e({totalImages:0,totalSize:0,channels:0})}}):{totalImages:0,totalSize:0,channels:0}}function wt(e){var t,a,n,o;if(!u.value.bots[e.selfId])u.value.bots[e.selfId]={selfId:e.selfId,platform:e.platform,username:((t=e.bot)==null?void 0:t.name)||`Bot-${e.selfId}`,avatar:(a=e.bot)==null?void 0:a.avatar,status:"online"};else{const s=u.value.bots[e.selfId];s.status="online",(n=e.bot)!=null&&n.name&&s.username!==e.bot.name&&(s.username=e.bot.name),(o=e.bot)!=null&&o.avatar&&s.avatar!==e.bot.avatar&&(s.avatar=e.bot.avatar)}if(u.value.channels[e.selfId]||(u.value.channels[e.selfId]={}),e.channelId&&!u.value.channels[e.selfId][e.channelId]){const s=e.guildId?`${e.guildName||e.guildId} (${e.channelId})`:`私信 ${e.channelId}`;u.value.channels[e.selfId][e.channelId]={id:e.channelId,name:s,type:e.channelType||0,guildId:e.guildId,guildName:e.guildName||e.guildId||"私聊"}}if(e.messageId&&e.content&&e.channelId){const s=`${e.selfId}:${e.channelId}`;if(u.value.messages[s]||(u.value.messages[s]=[]),!u.value.messages[s].find(c=>c.id===e.messageId)){const c={id:e.messageId,content:e.content,userId:e.userId,username:e.username,avatar:e.avatar,timestamp:e.timestamp,channelId:e.channelId,selfId:e.selfId,elements:e.elements,isBot:false,quote:e.quote},d=u.value.messages[s];let p=d.length;for(let w=d.length-1;w>=0;w--){if(d[w].timestamp<=e.timestamp){p=w+1;break}w===0&&(p=0)}d.splice(p,0,c),d.length>100&&(u.value.messages[s]=d.slice(-100)),q.value[s]=d.length;const k=Me();Ie(()=>{setTimeout(()=>{k&&ve()},10)})}}if(e.elements&&e.elements.length>0){const s=`${e.selfId}:${e.channelId}`;e.elements.forEach(i=>{if((i.type==="img"||i.type==="image"||i.type==="mface")&&i.attrs){const c=i.attrs.src||i.attrs.url||i.attrs.file;c&&we(s,c).catch(d=>{console.warn("预缓存图片失败:",c,d)})}})}u.value={...u.value}}function sa(e){const t=`${e.selfId}:${e.channelId}`;if(u.value.messages[t]||(u.value.messages[t]=[]),!u.value.messages[t].find(n=>n.id===e.messageId)){const n={id:e.messageId,content:e.content,userId:e.selfId,username:e.botUsername,avatar:e.botAvatar,timestamp:e.timestamp,channelId:e.channelId,selfId:e.selfId,elements:e.elements,isBot:true,quote:e.quote},o=u.value.messages[t];let s=o.length;for(let c=o.length-1;c>=0;c--){if(o[c].timestamp<=e.timestamp){s=c+1;break}c===0&&(s=0)}o.splice(s,0,n),o.length>100&&(u.value.messages[t]=o.slice(-100)),q.value[t]=o.length;const i=Me();Ie(()=>{setTimeout(()=>{i&&ve()},10)})}u.value={...u.value}}function oa(e){var t,a,n,o;if(!u.value.bots[e.selfId])u.value.bots[e.selfId]={selfId:e.selfId,platform:e.platform,username:((t=e.bot)==null?void 0:t.name)||`Bot-${e.selfId}`,avatar:(a=e.bot)==null?void 0:a.avatar,status:"online"};else{const s=u.value.bots[e.selfId];s.status="online",(n=e.bot)!=null&&n.name&&s.username!==e.bot.name&&(s.username=e.bot.name),(o=e.bot)!=null&&o.avatar&&s.avatar!==e.bot.avatar&&(s.avatar=e.bot.avatar)}if(u.value.channels[e.selfId]||(u.value.channels[e.selfId]={}),e.channelId&&!u.value.channels[e.selfId][e.channelId]){const s=e.guildId?`${e.guildName||e.guildId} (${e.channelId})`:`私信 ${e.channelId}`;u.value.channels[e.selfId][e.channelId]={id:e.channelId,name:s,type:e.channelType||0,guildId:e.guildId,guildName:e.guildName||e.guildId||"私聊"}}if(e.messageId&&e.content&&e.channelId){const s=`${e.selfId}:${e.channelId}`;if(u.value.messages[s]||(u.value.messages[s]=[]),!u.value.messages[s].find(c=>c.id===e.messageId)){const c={id:e.messageId,content:e.content,userId:e.userId,username:e.username,avatar:e.avatar,timestamp:e.timestamp,channelId:e.channelId,selfId:e.selfId,elements:e.elements,isBot:true,quote:e.quote},d=u.value.messages[s];let p=d.length;for(let w=d.length-1;w>=0;w--){if(d[w].timestamp<=e.timestamp){p=w+1;break}w===0&&(p=0)}d.splice(p,0,c),d.length>100&&(u.value.messages[s]=d.slice(-100)),q.value[s]=d.length;const k=Me();Ie(()=>{setTimeout(()=>{k&&ve()},10)})}}if(e.elements&&e.elements.length>0){const s=`${e.selfId}:${e.channelId}`;e.elements.forEach(i=>{if((i.type==="img"||i.type==="image"||i.type==="mface")&&i.attrs){const c=i.attrs.src||i.attrs.url||i.attrs.file;c&&we(s,c).catch(d=>{console.warn("预缓存图片失败:",c,d)})}})}u.value={...u.value}}async function ra(){try{const e=await P("get-chat-data");if(e.success&&e.data){const t={};W.value=new Set(e.data.pinnedBots||[]),oe.value=new Set(e.data.pinnedChannels||[]);for(const[a,n]of Object.entries(e.data.messages||{})){const o=n.map(s=>({id:s.id,content:s.content,userId:s.userId,username:s.username,avatar:s.avatar,timestamp:s.timestamp,channelId:s.channelId,selfId:s.selfId,elements:s.elements,isBot:s.type==="bot",quote:s.quote}));o.sort((s,i)=>s.timestamp-i.timestamp),t[a]=o}return u.value={bots:e.data.bots||{},channels:e.data.channels||{},messages:t},await la(),true}else return console.warn("获取聊天数据失败:",e.error),false}catch(e){return console.error("获取聊天数据时出错:",e),false}}async function la(){try{const e=await P("get-all-channel-message-counts");if(e.success&&e.counts){const t={};for(const[a,n]of Object.entries(e.counts))t[a]=n;q.value=t}else console.warn("获取频道消息数量失败:",e.error)}catch(e){console.error("获取频道消息数量时出错:",e)}}async function ca(){try{const e=await P("get-plugin-config");e.success&&e.config?ce.value=e.config:console.warn("获取插件配置失败:",e.error)}catch(e){console.error("获取插件配置时出错:",e)}}async function It(e,t){try{const a=await P("get-history-messages",{selfId:e,channelId:t});if(a.success&&a.messages){const n=`${e}:${t}`,o=a.messages.map(s=>({id:s.id,content:s.content,userId:s.userId,username:s.username,avatar:s.avatar,timestamp:s.timestamp,channelId:s.channelId,selfId:s.selfId,elements:s.elements,isBot:s.type==="bot",quote:s.quote}));return o.sort((s,i)=>s.timestamp-i.timestamp),u.value.messages[n]=o,q.value[n]=o.length,u.value={...u.value},true}else return console.warn("获取历史消息失败:",a.error),false}catch(a){return console.error("获取历史消息时出错:",a),false}}function ia(e){if(!L.value||e.touches.length!==1)return;const t=e.touches[0];F.value={x:t.clientX,y:t.clientY,time:Date.now()},ae.value={x:t.clientX,y:t.clientY},Be.value=false}function ua(e){if(!L.value||!F.value||e.touches.length!==1)return;const t=e.touches[0];ae.value={x:t.clientX,y:t.clientY};const a=t.clientX-F.value.x,n=t.clientY-F.value.y;if(Math.abs(a)>Math.abs(n)&&Math.abs(a)>30){const o=a>0,s=V.value==="messages"||V.value==="channels";if(o&&s){Be.value=true;const i=Math.min(a,200),c=150;i>c?fe.value={show:true,text:"松开返回"}:fe.value={show:true,text:`滑动返回 ${Math.round(i/c*100)}%`},e.preventDefault()}else fe.value={show:false,text:""}}else fe.value={show:false,text:""}}function da(e){if(!L.value||!F.value)return;const a=Date.now()-F.value.time;if(ae.value){const n=ae.value.x-F.value.x,o=ae.value.y-F.value.y,s=n>150,i=Math.abs(n)>Math.abs(o),c=a<300&&n>80;(s&&i||c)&&fa()}F.value=null,ae.value=null,Be.value=false,fe.value={show:false,text:""}}function fa(){switch(V.value){case"messages":V.value="channels";break;case"channels":V.value="bots",g.value="",$.value="";break}}function at(){L.value=window.innerWidth<=768}function xt(){return!ne.value||Me()}const Ct=()=>{L.value&&B.value&&Ie(()=>{xt()&&ve()})},ha=()=>{L.value&&setTimeout(()=>{B.value&&xt()&&ve()},300)};return kt(D,(e,t)=>{t.length===0&&e.length>0&&Ie(()=>{ve()})}),nt(async()=>{at(),window.addEventListener("resize",at),window.visualViewport&&window.visualViewport.addEventListener("resize",Ct),document.addEventListener("click",Ee),await Et()?(console.log("IndexedDB初始化成功"),setTimeout(async()=>{await et()},2e3),setInterval(async()=>{await et()},5*60*1e3)):console.warn("IndexedDB初始化失败,图片缓存功能将不可用"),await ca(),await ra();const t=rt("chat-message-event",wt),a=rt("bot-message-sent-event",sa),n=rt("chat-bot-message-event",oa);kt($,o=>{o&&Ie(()=>{B.value&&(B.value.removeEventListener("scroll",Ke),B.value.addEventListener("scroll",Ke),Ke()),!L.value&&he.value&&he.value.focus()})},{immediate:true}),setInterval(()=>{Je()},2*60*1e3),ma(()=>{window.removeEventListener("resize",at),window.visualViewport&&window.visualViewport.removeEventListener("resize",Ct),document.removeEventListener("click",Ee),t&&typeof t=="function"&&t(),a&&typeof a=="function"&&a(),n&&typeof n=="function"&&n(),B.value&&B.value.removeEventListener("scroll",Ke),Object.values(b.value).forEach(o=>{URL.revokeObjectURL(o)}),b.value={},I&&(I.close(),I=null)})}),{AvatarComponent:le,ImageComponent:X,JsonCardComponent:ge,ForwardMessageComponent:G,MessageElement:ke,chatData:u,channelMessageCounts:q,pluginConfig:ce,selectedBot:g,selectedChannel:$,inputMessage:Se,imageBlobUrls:b,pinnedBots:W,pinnedChannels:oe,uploadedImages:Y,showActionMenu:de,isMobile:L,mobileView:V,touchStart:F,touchCurrent:ae,isSwipeActive:Be,swipeIndicator:fe,messageHistory:B,messageInput:he,showScrollButton:$e,isUserScrolling:ne,isSending:me,draggingChannel:se,dragStartPos:M,dragCurrentPos:A,dragElementInitialPos:_e,dragOffset:pe,dragThreshold:H,isDragReady:Z,draggedBubbleElement:C,contextMenu:N,fileInput:Le,bots:m,currentChannels:l,currentMessages:D,currentChannelName:Ue,currentChannelKey:$t,canSendMessage:lt,canInputMessage:_t,mobileViewClass:Dt,inputPlaceholder:Tt,chatContainerStyle:Lt,selectBot:qt,selectChannel:jt,handleBotRightClick:Ut,handleChannelRightClick:Kt,showContextMenu:Ge,hideContextMenu:J,handleKeyDown:Ze,toggleBotPin:Mt,toggleChannelPin:At,deleteBotMessages:zt,deleteChannelMessages:Pt,sendMessage:Nt,toggleActionMenu:Rt,triggerImageUpload:Ot,handleFileSelect:Ft,handlePaste:Ht,uploadImage:Qe,removeImage:Xt,fileToBase64:ut,handleClickOutside:Ee,formatTime:Yt,getChannelTypeText:Vt,scrollToBottom:ve,checkScrollPosition:Ke,isNearBottom:Me,getChannelMessageCount:dt,startDrag:Wt,handleDragMove:Ae,handleDragEnd:ze,resetDragState:Pe,getDragStyle:Jt,getDragDistance:Gt,clearChannelHistory:ft,showNotification:T,createThresholdCircle:ht,removeThresholdCircle:mt,handleTouchStart:ia,handleTouchMove:ua,handleTouchEnd:da,handleInputFocus:ha,getCachedImageUrl:Ve,cacheImage:we,clearChannelImageCache:je,getMemoryStats:aa,getCacheStats:na,isFileUrl:ee,loadHistoryMessages:It,handleMessageEvent:wt}}const Ca={class:"bot-list"},ka={class:"bot-items"},ba=["onClick","onContextmenu"],Sa={class:"bot-avatar"},Ba={key:1,class:"avatar-placeholder"},$a={class:"bot-info"},_a={class:"bot-name"},Da={class:"bot-platform"},Ta={class:"channel-list"},La={key:0,class:"empty-state"},qa={key:1,class:"channel-items"},Ua=["data-channel-id","onClick","onContextmenu"],Ka={class:"channel-info"},Ma={class:"channel-name"},Aa={class:"channel-type"},za=["onMousedown","onTouchstart","title"],Pa={class:"message-area"},ja={class:"panel-header"},Na={key:0,class:"empty-state"},Ra={key:1,class:"message-content"},Oa={class:"message-avatar"},Fa={key:1,class:"avatar-placeholder"},Ha={class:"message-content-wrapper"},Xa={class:"message-header"},Ya={class:"message-username"},Va={class:"message-time"},Wa={key:0,class:"message-quote"},Ja={class:"quote-header"},Ga={class:"quote-avatar"},Za={key:1,class:"avatar-placeholder"},Qa={class:"quote-username"},Ea={class:"quote-time"},en={class:"quote-content"},tn={class:"message-text"},an={class:"message-input"},nn={key:0,class:"image-preview-container"},sn=["src","alt"],on=["onClick"],rn={class:"input-row"},ln={class:"input-actions"},cn=["placeholder","disabled"],un=["disabled"],dn=Ce({__name:"index",setup(ee){const le=xa(),{AvatarComponent:X,MessageElement:ge,selectedBot:G,selectedChannel:ke,inputMessage:u,pinnedBots:q,pinnedChannels:ce,uploadedImages:b,showActionMenu:be,swipeIndicator:ie,messageHistory:ye,messageInput:I,showScrollButton:Re,isSending:Oe,draggingChannel:S,dragThreshold:te,contextMenu:U,fileInput:ue,bots:Te,currentChannels:Fe,currentMessages:We,currentChannelName:O,currentChannelKey:K,canSendMessage:He,canInputMessage:g,mobileViewClass:$,inputPlaceholder:Se,chatContainerStyle:Y,selectBot:de,selectChannel:Le,handleBotRightClick:L,handleChannelRightClick:V,toggleBotPin:F,toggleChannelPin:ae,deleteBotMessages:Be,deleteChannelMessages:fe,sendMessage:B,toggleActionMenu:he,triggerImageUpload:$e,handleFileSelect:ne,handlePaste:me,removeImage:se,formatTime:M,getChannelTypeText:A,scrollToBottom:_e,getChannelMessageCount:pe,startDrag:H,getDragStyle:qe,getDragDistance:j,handleTouchStart:Z,handleTouchMove:C,handleTouchEnd:N,handleInputFocus:W}=le;return(oe,m)=>(y(),x("div",{class:re(["chat-container",r($)]),style:st(r(Y)),onTouchstart:m[15]||(m[15]=(...l)=>r(Z)&&r(Z)(...l)),onTouchmove:m[16]||(m[16]=(...l)=>r(C)&&r(C)(...l)),onTouchend:m[17]||(m[17]=(...l)=>r(N)&&r(N)(...l))},[f("div",Ca,[m[18]||(m[18]=f("div",{class:"panel-header"},[f("h3",null,"机器人")],-1)),f("div",ka,[(y(true),x(E,null,De(r(Te),l=>(y(),x("div",{key:l.selfId,class:re(["bot-item",{active:r(G)===l.selfId,pinned:r(q).has(l.selfId)}]),onClick:D=>r(de)(l.selfId),onContextmenu:D=>r(L)(D,l.selfId)},[f("div",Sa,[l.avatar?(y(),Ne(r(X),{key:0,src:l.avatar,alt:l.username,"channel-key":"bot-list"},null,8,["src","alt"])):(y(),x("div",Ba,_(l.username.charAt(0).toUpperCase()),1))]),f("div",$a,[f("div",_a,_(l.username),1),f("div",Da,_(l.platform),1)]),f("div",{class:re(["bot-status",l.status])},null,2)],42,ba))),128))])]),f("div",Ta,[m[19]||(m[19]=f("div",{class:"panel-header"},[f("h3",null,"频道")],-1)),r(G)?(y(),x("div",qa,[(y(true),x(E,null,De(r(Fe),l=>(y(),x("div",{key:l.id,class:re(["channel-item",{active:r(ke)===l.id,pinned:r(ce).has(`${r(G)}:${l.id}`)}]),"data-channel-id":l.id,onClick:D=>r(Le)(l.id),onContextmenu:D=>r(V)(D,l.id)},[f("div",Ka,[f("div",Ma,_(l.name),1),f("div",Aa,_(r(A)(l.type)),1)]),r(pe)(l.id)>0?(y(),x("div",{key:0,class:re(["channel-message-count draggable-bubble",{dragging:r(S)===l.id,"will-delete":r(S)===l.id&&r(j)(l.id)>r(te)}]),onMousedown:D=>r(H)(D,l.id),onTouchstart:D=>r(H)(D,l.id),style:st(r(qe)(l.id)),title:r(S)===l.id?r(j)(l.id)>r(te)?"松开清理历史记录":"拖拽更远以清理历史记录":"拖拽清理历史记录"},_(r(pe)(l.id)),47,za)):xe("",true)],42,Ua))),128))])):(y(),x("div",La," 请选择一个机器人 "))]),f("div",Pa,[f("div",ja,[f("h3",null,_(r(O)||"选择频道"),1)]),!r(G)||!r(ke)?(y(),x("div",Na," 请选择机器人和频道 ")):(y(),x("div",Ra,[f("div",{class:"message-history",ref_key:"messageHistory",ref:ye},[(y(true),x(E,null,De(r(We),l=>(y(),x("div",{key:l.id,class:re(["message-item",{"bot-message":l.isBot}])},[f("div",Oa,[l.avatar?(y(),Ne(r(X),{key:0,src:l.avatar,alt:l.username,"channel-key":r(K)},null,8,["src","alt","channel-key"])):(y(),x("div",Fa,_(l.username.charAt(0).toUpperCase()),1))]),f("div",Ha,[f("div",Xa,[f("span",Ya,_(l.username),1),f("span",Va,_(r(M)(l.timestamp)),1)]),l.quote?(y(),x("div",Wa,[f("div",Ja,[f("div",Ga,[l.quote.user.avatar?(y(),Ne(r(X),{key:0,src:l.quote.user.avatar,alt:l.quote.user.username,"channel-key":r(K)},null,8,["src","alt","channel-key"])):(y(),x("div",Za,_(l.quote.user.username.charAt(0).toUpperCase()),1))]),f("span",Qa,_(l.quote.user.username),1),f("span",Ea,_(r(M)(l.quote.timestamp)),1)]),f("div",en,[l.quote.elements&&l.quote.elements.length>0?(y(true),x(E,{key:0},De(l.quote.elements,(D,Ue)=>(y(),Ne(r(ge),{key:`quote-${Ue}`,element:D,"channel-key":r(K)},null,8,["element","channel-key"]))),128)):(y(),x(E,{key:1},[ot(_(l.quote.content),1)],64))])])):xe("",true),f("div",tn,[l.elements&&l.elements.length>0?(y(true),x(E,{key:0},De(l.elements,(D,Ue)=>(y(),Ne(r(ge),{key:Ue,element:D,"channel-key":r(K)},null,8,["element","channel-key"]))),128)):(y(),x(E,{key:1},[ot(_(l.content),1)],64))])])],2))),128))],512),bt(f("div",{class:"floating-scroll-button",onClick:m[0]||(m[0]=(...l)=>r(_e)&&r(_e)(...l))},m[20]||(m[20]=[f("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},[f("path",{d:"M7 10l5 5 5-5z"})],-1)]),512),[[va,r(Re)]]),f("div",an,[r(b).length>0?(y(),x("div",nn,[(y(true),x(E,null,De(r(b),l=>(y(),x("div",{key:l.tempId,class:"image-preview-item"},[f("img",{src:l.preview,alt:l.filename,class:"preview-image"},null,8,sn),f("button",{class:"remove-image-btn",onClick:D=>r(se)(l.tempId),title:"删除图片"},m[21]||(m[21]=[f("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"currentColor"},[f("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"})],-1)]),8,on)]))),128))])):xe("",true),f("div",rn,[f("div",ln,[f("button",{class:re(["add-button",{active:r(be)}]),onClick:m[1]||(m[1]=(...l)=>r(he)&&r(he)(...l)),title:"更多操作"},m[22]||(m[22]=[f("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2.5","stroke-linecap":"round","stroke-linejoin":"round"},[f("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),f("line",{x1:"5",y1:"12",x2:"19",y2:"12"})],-1)]),2),r(be)?(y(),x("div",{key:0,class:"action-menu",onClick:m[3]||(m[3]=St(()=>{},["stop"]))},[f("button",{class:"action-menu-item",onClick:m[2]||(m[2]=(...l)=>r($e)&&r($e)(...l))},m[23]||(m[23]=[f("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[f("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),f("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),f("polyline",{points:"21,15 16,10 5,21"})],-1),ot(" 上传图片 ",-1)]))])):xe("",true)]),bt(f("input",{"onUpdate:modelValue":m[4]||(m[4]=l=>ya(u)?u.value=l:null),type:"text",placeholder:r(Se),onKeyup:m[5]||(m[5]=ga((...l)=>r(B)&&r(B)(...l),["enter"])),disabled:!r(g),ref_key:"messageInput",ref:I,onPaste:m[6]||(m[6]=(...l)=>r(me)&&r(me)(...l)),onFocus:m[7]||(m[7]=(...l)=>r(W)&&r(W)(...l))},null,40,cn),[[pa,r(u)]]),f("button",{onClick:m[8]||(m[8]=(...l)=>r(B)&&r(B)(...l)),disabled:!r(He),class:re({"is-sending":r(Oe)})},_(r(Oe)?"发送中...":"发送"),11,un)]),f("input",{type:"file",ref_key:"fileInput",ref:ue,onChange:m[9]||(m[9]=(...l)=>r(ne)&&r(ne)(...l)),accept:"image/*",multiple:"",style:{display:"none"}},null,544)])]))]),r(U).show?(y(),x("div",{key:0,class:"context-menu",style:st({left:r(U).x+"px",top:r(U).y+"px"}),onClick:m[14]||(m[14]=St(()=>{},["stop"]))},[r(U).type==="bot"?(y(),x(E,{key:0},[f("div",{class:"context-menu-item",onClick:m[10]||(m[10]=l=>r(F)(r(U).targetId))},_(r(q).has(r(U).targetId)?"取消置顶":"置顶"),1),f("div",{class:"context-menu-item danger",onClick:m[11]||(m[11]=l=>r(Be)(r(U).targetId))}," 彻底删除此机器人所有数据 ")],64)):xe("",true),r(U).type==="channel"?(y(),x(E,{key:1},[f("div",{class:"context-menu-item",onClick:m[12]||(m[12]=l=>r(ae)(r(U).targetId))},_(r(ce).has(`${r(G)}:${r(U).targetId}`)?"取消置顶":"置顶"),1),f("div",{class:"context-menu-item danger",onClick:m[13]||(m[13]=l=>r(fe)(r(U).targetId))}," 彻底删除此频道所有数据 ")],64)):xe("",true)],4)):xe("",true),f("div",{class:re(["swipe-indicator",{show:r(ie).show}])},_(r(ie).text),3)],38))}}),Bt=(ee,le)=>{const X=ee.__vccOpts||ee;for(const[ge,G]of le)X[ge]=G;return X},fn=Bt(dn,[["__scopeId","data-v-de93bb69"]]),hn={},mn={class:"k-icon",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none"};function vn(ee,le){return y(),x("svg",mn,le[0]||(le[0]=[f("path",{d:"M8 10.5H16",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),f("path",{d:"M8 14H13.5",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),f("path",{d:"M17 3.33782C15.5291 2.48697 13.8214 2 12 2C6.47715 2 2 6.47715 2 12C2 13.5997 2.37562 15.1116 3.04346 16.4525C3.22094 16.8088 3.28001 17.2161 3.17712 17.6006L2.58151 19.8267C2.32295 20.793 3.20701 21.677 4.17335 21.4185L6.39939 20.8229C6.78393 20.72 7.19121 20.7791 7.54753 20.9565C8.88837 21.6244 10.4003 22 12 22C17.5228 22 22 17.5228 22 12C22 10.1786 21.513 8.47087 20.6622 7",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)]))}const gn=Bt(hn,[["render",vn]]);Ia.register("activity:chat",gn);const wn=ee=>{ee.page({name:"聊天室",path:"/chat-patch",desc:"",authority:4,icon:"activity:chat",component:Ce({setup(){return()=>h(wa("k-layout"),{},{default:()=>h(fn)})}})})};export{wn as default};
22
+ `,document.head.appendChild(o),document.body.appendChild(a),setTimeout(()=>{a.style.animation="slideOut 0.3s ease-in",setTimeout(()=>{a.parentNode&&a.parentNode.removeChild(a),o.parentNode&&o.parentNode.removeChild(o)},300)},3e3)}function mt(e,t){const a=document.createElement("div");a.className="drag-threshold-circle",a.style.cssText=`
23
+ left: ${e-X}px;
24
+ top: ${t-X}px;
25
+ width: ${X*2}px;
26
+ height: ${X*2}px;
27
+ `,document.body.appendChild(a),window.dragThresholdCircle=a}function vt(){const e=window.dragThresholdCircle;e&&e.parentNode&&(e.parentNode.removeChild(e),window.dragThresholdCircle=null)}async function et(){try{if(!I)return false;const e=Date.now();if(e-He<We)return true;He=e;const t=await gt();F=t.totalSize,K=t.totalImages,console.log("数据库健康检查:",{大小:`${(F/1024/1024).toFixed(2)}MB / ${(ae/1024/1024).toFixed(2)}MB`,图片数量:`${K} / ${de}`,使用率:`${(F/ae*100).toFixed(1)}%`});const a=F/ae,n=K/de;return(a>Fe||n>Fe)&&(console.warn("数据库使用率过高,开始自动清理"),await Ye()),(a>.95||n>.95)&&(console.error("数据库接近极限,执行紧急清理"),await Et()),true}catch(e){return console.error("数据库健康检查失败:",e),false}}async function gt(){return I?new Promise(e=>{const n=I.transaction([$],"readonly").objectStore($).getAll();n.onsuccess=()=>{const o=n.result||[];let s=0;const i={};o.forEach(c=>{s+=c.size||0,i[c.channelKey]=(i[c.channelKey]||0)+1}),e({totalSize:s,totalImages:o.length,channelStats:i})},n.onerror=()=>{console.error("获取数据库统计失败:",n.error),e({totalSize:0,totalImages:0,channelStats:{}})}}):{totalSize:0,totalImages:0,channelStats:{}}}async function Ye(){try{console.log("开始自动清理...");const e=await yt();if(e.length===0)return;const t={};e.forEach(o=>{t[o.channelKey]||(t[o.channelKey]=[]),t[o.channelKey].push(o)});let a=0,n=0;for(const[o,s]of Object.entries(t))if(s.length>M){s.sort((c,d)=>c.timestamp-d.timestamp);const i=s.slice(0,s.length-M);for(const c of i)await tt(c.url),a++,n+=c.size||0,b.value[c.url]&&(URL.revokeObjectURL(b.value[c.url]),delete b.value[c.url])}console.log(`自动清理完成: 清理了 ${a} 张图片,释放了 ${(n/1024/1024).toFixed(2)}MB`),K-=a,F-=n}catch(e){console.error("自动清理失败:",e)}}async function Et(){try{console.log("开始紧急清理...");const e=await yt();if(e.length===0)return;e.sort((s,i)=>i.timestamp-s.timestamp);const t=Math.floor(de*.3),a=e.slice(t);let n=0,o=0;for(const s of a)await tt(s.url),n++,o+=s.size||0,b.value[s.url]&&(URL.revokeObjectURL(b.value[s.url]),delete b.value[s.url]);console.log(`紧急清理完成: 清理了 ${n} 张图片,释放了 ${(o/1024/1024).toFixed(2)}MB`),K=t,F-=o}catch(e){console.error("紧急清理失败:",e)}}async function yt(){return I?new Promise(e=>{const n=I.transaction([$],"readonly").objectStore($).getAll();n.onsuccess=()=>{e(n.result||[])},n.onerror=()=>{console.error("获取所有图片失败:",n.error),e([])}}):[]}async function ea(){return new Promise(e=>{try{I&&(I.close(),I=null);const t=indexedDB.deleteDatabase(Ne);t.onsuccess=()=>{console.log("IndexedDB数据库已完全清理"),F=0,K=0,e(true)},t.onerror=()=>{console.error("清理IndexedDB数据库失败:",t.error),e(false)},t.onblocked=()=>{console.warn("IndexedDB数据库删除被阻塞,可能有其他连接正在使用"),setTimeout(()=>{e(false)},5e3)}}catch(t){console.error("清理数据库时出错:",t),e(false)}})}async function ta(){try{return await pt()?(setTimeout(async()=>{const t=await gt();console.log("数据库初始状态:",{大小:`${(t.totalSize/1024/1024).toFixed(2)}MB`,图片数量:t.totalImages,频道分布:t.channelStats}),(t.totalSize>ae*.9||t.totalImages>de*.9)&&(console.warn("数据库初始状态接近限制,执行清理"),await Ye())},1e3),true):(console.warn("数据库打开失败,尝试清理后重新初始化"),await ea(),await pt())}catch(e){return console.error("IndexedDB初始化出错:",e),false}}async function pt(){return new Promise(e=>{try{const t=indexedDB.open(Ne,Oe);t.onerror=()=>{console.error("IndexedDB打开失败:",t.error),e(false)},t.onsuccess=()=>{I=t.result,I.onerror=a=>{console.error("IndexedDB运行时错误:",a)},I.onversionchange=()=>{console.warn("IndexedDB版本变更,关闭连接"),I==null||I.close(),I=null},e(true)},t.onupgradeneeded=a=>{const n=a.target.result;if(!n.objectStoreNames.contains($)){const o=n.createObjectStore($,{keyPath:"url"});o.createIndex("channelKey","channelKey",{unique:false}),o.createIndex("timestamp","timestamp",{unique:false}),o.createIndex("size","size",{unique:false}),console.log("IndexedDB对象存储创建完成")}},t.onblocked=()=>{console.warn("IndexedDB打开被阻塞"),e(false)}}catch(t){console.error("打开数据库时出错:",t),e(false)}})}async function aa(e){return I?new Promise((t,a)=>{const s=I.transaction([$],"readonly").objectStore($).get(e);s.onsuccess=()=>{t(s.result||null)},s.onerror=()=>{console.error("从IndexedDB获取图片失败:",s.error),t(null)}}):null}async function wt(e){if(!I)return false;try{return e.size>Le?(console.warn(`图片过大,跳过缓存: ${(e.size/1024/1024).toFixed(2)}MB > ${(Le/1024/1024).toFixed(2)}MB`),false):(await et(),F+e.size>ae&&(console.warn("添加图片会超过数据库大小限制,执行清理"),await Ye(),F+e.size>ae)?(console.warn("清理后仍会超过限制,跳过此图片"),false):K>=de&&(console.warn("图片数量已达上限,执行清理"),await Ye(),K>=de)?(console.warn("清理后仍达上限,跳过此图片"),false):new Promise(t=>{const o=I.transaction([$],"readwrite").objectStore($).put(e);o.onsuccess=()=>{F+=e.size,K+=1,t(true)},o.onerror=()=>{console.error("保存图片到IndexedDB失败:",o.error),t(false)}}))}catch(t){return console.error("保存图片时出错:",t),false}}async function tt(e){return I?new Promise(t=>{const o=I.transaction([$],"readwrite").objectStore($).delete(e);o.onsuccess=()=>{t(true)},o.onerror=()=>{console.error("从IndexedDB删除图片失败:",o.error),t(false)}}):false}async function na(e){return I?new Promise(t=>{const s=I.transaction([$],"readonly").objectStore($).index("channelKey").getAll(e);s.onsuccess=()=>{t(s.result||[])},s.onerror=()=>{console.error("获取频道图片失败:",s.error),t([])}}):[]}async function Ve(e,t){const a=b.value[t];if(a)return a;const n=await aa(t);if(!n)return null;Je();const o=URL.createObjectURL(n.blob);return b.value[t]=o,Xe(it(n.blob)),n.timestamp=Date.now(),await wt(n),o}async function xe(e,t){try{const a=await Ve(e,t);if(a)return a;const n=await P("fetch-image",{url:t});if(!n.success)return console.error("获取图片失败:",n.error),null;const o=n.base64,s=n.contentType||"image/jpeg",i=atob(o),c=new Array(i.length);for(let z=0;z<i.length;z++)c[z]=i.charCodeAt(z);const d=new Uint8Array(c),p=new Blob([d],{type:s});if(p.size>Le)return console.warn(`图片过大,跳过缓存: ${(p.size/1024/1024).toFixed(2)}MB`),null;const k={url:t,blob:p,timestamp:Date.now(),size:p.size,channelKey:e};if(!await wt(k))return console.error("保存图片到IndexedDB失败"),null;Je();const O=URL.createObjectURL(p);return b.value[t]=O,Xe(it(p)),O}catch(a){return console.error("缓存图片失败:",a),null}}async function Pe(e){try{const t=await na(e);let a=0;for(const n of t)await tt(n.url),b.value[n.url]&&(URL.revokeObjectURL(b.value[n.url]),delete b.value[n.url],a+=n.size||0);a>0&&Xe(-a)}catch(t){console.error("清理频道图片缓存失败:",t)}}function sa(){const e=Object.keys(b.value).length;return{blobCount:e,estimatedMemoryUsage:we,maxMemoryLimit:be,maxBlobLimit:ue,memoryUsagePercent:(we/be*100).toFixed(1),blobUsagePercent:(e/ue*100).toFixed(1)}}async function oa(){return I?new Promise(e=>{const n=I.transaction([$],"readonly").objectStore($).getAll();n.onsuccess=()=>{const o=n.result||[],s=new Set;let i=0;o.forEach(c=>{s.add(c.channelKey),i+=c.size}),e({totalImages:o.length,totalSize:i,channels:s.size})},n.onerror=()=>{console.error("获取缓存统计失败:",n.error),e({totalImages:0,totalSize:0,channels:0})}}):{totalImages:0,totalSize:0,channels:0}}function at(){g.value&&S.value&&(localStorage.setItem("chat-selected-bot",g.value),localStorage.setItem("chat-selected-channel",S.value))}function It(){const e=localStorage.getItem("chat-selected-bot"),t=localStorage.getItem("chat-selected-channel");return e&&t&&u.value.bots[e]&&u.value.channels[e]&&u.value.channels[e][t]?(g.value=e,S.value=t,true):false}function xt(e){var t,a,n,o;if(!u.value.bots[e.selfId])u.value.bots[e.selfId]={selfId:e.selfId,platform:e.platform,username:((t=e.bot)==null?void 0:t.name)||`Bot-${e.selfId}`,avatar:(a=e.bot)==null?void 0:a.avatar,status:"online"};else{const s=u.value.bots[e.selfId];s.status="online",(n=e.bot)!=null&&n.name&&s.username!==e.bot.name&&(s.username=e.bot.name),(o=e.bot)!=null&&o.avatar&&s.avatar!==e.bot.avatar&&(s.avatar=e.bot.avatar)}if(u.value.channels[e.selfId]||(u.value.channels[e.selfId]={}),e.channelId&&!u.value.channels[e.selfId][e.channelId]){const s=e.isDirect?`私信 ${e.channelId}`:`${e.guildName||e.channelId} (${e.channelId})`;u.value.channels[e.selfId][e.channelId]={id:e.channelId,name:s,type:e.channelType||0,channelId:e.channelId,guildName:e.guildName||"群聊",isDirect:e.isDirect}}if(e.messageId&&e.content&&e.channelId){const s=`${e.selfId}:${e.channelId}`;if(u.value.messages[s]||(u.value.messages[s]=[]),!u.value.messages[s].find(c=>c.id===e.messageId)){const c={id:e.messageId,content:e.content,userId:e.userId,username:e.username,avatar:e.avatar,timestamp:e.timestamp,channelId:e.channelId,selfId:e.selfId,elements:e.elements,isBot:false,quote:e.quote},d=u.value.messages[s];let p=d.length;for(let w=d.length-1;w>=0;w--){if(d[w].timestamp<=e.timestamp){p=w+1;break}w===0&&(p=0)}d.splice(p,0,c),d.length>100&&(u.value.messages[s]=d.slice(-100)),U.value[s]=d.length;const k=Ke();ye(()=>{setTimeout(()=>{k&&ge()},10)})}}if(e.elements&&e.elements.length>0){const s=`${e.selfId}:${e.channelId}`;e.elements.forEach(i=>{if((i.type==="img"||i.type==="image"||i.type==="mface")&&i.attrs){const c=i.attrs.src||i.attrs.url||i.attrs.file;c&&xe(s,c).catch(d=>{console.warn("预缓存图片失败:",c,d)})}})}u.value={...u.value}}function ra(e){const t=`${e.selfId}:${e.channelId}`;if(u.value.messages[t]||(u.value.messages[t]=[]),!u.value.messages[t].find(n=>n.id===e.messageId)){const n={id:e.messageId,content:e.content,userId:e.selfId,username:e.botUsername,avatar:e.botAvatar,timestamp:e.timestamp,channelId:e.channelId,selfId:e.selfId,elements:e.elements,isBot:true,quote:e.quote},o=u.value.messages[t];let s=o.length;for(let c=o.length-1;c>=0;c--){if(o[c].timestamp<=e.timestamp){s=c+1;break}c===0&&(s=0)}o.splice(s,0,n),o.length>100&&(u.value.messages[t]=o.slice(-100)),U.value[t]=o.length;const i=Ke();ye(()=>{setTimeout(()=>{i&&ge()},10)})}u.value={...u.value}}function la(e){var t,a,n,o;if(!u.value.bots[e.selfId])u.value.bots[e.selfId]={selfId:e.selfId,platform:e.platform,username:((t=e.bot)==null?void 0:t.name)||`Bot-${e.selfId}`,avatar:(a=e.bot)==null?void 0:a.avatar,status:"online"};else{const s=u.value.bots[e.selfId];s.status="online",(n=e.bot)!=null&&n.name&&s.username!==e.bot.name&&(s.username=e.bot.name),(o=e.bot)!=null&&o.avatar&&s.avatar!==e.bot.avatar&&(s.avatar=e.bot.avatar)}if(u.value.channels[e.selfId]||(u.value.channels[e.selfId]={}),e.channelId&&!u.value.channels[e.selfId][e.channelId]){const s=e.isDirect?`私信 ${e.channelId}`:`${e.guildName||e.channelId} (${e.channelId})`;u.value.channels[e.selfId][e.channelId]={id:e.channelId,name:s,type:e.channelType||0,channelId:e.channelId,guildName:e.guildName||"群聊",isDirect:e.isDirect}}if(e.messageId&&e.content&&e.channelId){const s=`${e.selfId}:${e.channelId}`;if(u.value.messages[s]||(u.value.messages[s]=[]),!u.value.messages[s].find(c=>c.id===e.messageId)){const c={id:e.messageId,content:e.content,userId:e.userId,username:e.username,avatar:e.avatar,timestamp:e.timestamp,channelId:e.channelId,selfId:e.selfId,elements:e.elements,isBot:true,quote:e.quote},d=u.value.messages[s];let p=d.length;for(let w=d.length-1;w>=0;w--){if(d[w].timestamp<=e.timestamp){p=w+1;break}w===0&&(p=0)}d.splice(p,0,c),d.length>100&&(u.value.messages[s]=d.slice(-100)),U.value[s]=d.length;const k=Ke();ye(()=>{setTimeout(()=>{k&&ge()},10)})}}if(e.elements&&e.elements.length>0){const s=`${e.selfId}:${e.channelId}`;e.elements.forEach(i=>{if((i.type==="img"||i.type==="image"||i.type==="mface")&&i.attrs){const c=i.attrs.src||i.attrs.url||i.attrs.file;c&&xe(s,c).catch(d=>{console.warn("预缓存图片失败:",c,d)})}})}u.value={...u.value}}async function ca(){try{const e=await P("get-chat-data");if(e.success&&e.data){const t={};J.value=new Set(e.data.pinnedBots||[]),re.value=new Set(e.data.pinnedChannels||[]);for(const[a,n]of Object.entries(e.data.messages||{})){const o=n.map(s=>({id:s.id,content:s.content,userId:s.userId,username:s.username,avatar:s.avatar,timestamp:s.timestamp,channelId:s.channelId,selfId:s.selfId,elements:s.elements,isBot:s.type==="bot",quote:s.quote}));o.sort((s,i)=>s.timestamp-i.timestamp),t[a]=o}return u.value={bots:e.data.bots||{},channels:e.data.channels||{},messages:t},await ia(),true}else return console.warn("获取聊天数据失败:",e.error),false}catch(e){return console.error("获取聊天数据时出错:",e),false}}async function ia(){try{const e=await P("get-all-channel-message-counts");if(e.success&&e.counts){const t={};for(const[a,n]of Object.entries(e.counts))t[a]=n;U.value=t}else console.warn("获取频道消息数量失败:",e.error)}catch(e){console.error("获取频道消息数量时出错:",e)}}async function ua(){try{const e=await P("get-plugin-config");e.success&&e.config?ie.value=e.config:console.warn("获取插件配置失败:",e.error)}catch(e){console.error("获取插件配置时出错:",e)}}async function Ct(e,t){try{const a=await P("get-history-messages",{selfId:e,channelId:t});if(a.success&&a.messages){const n=`${e}:${t}`,o=a.messages.map(s=>({id:s.id,content:s.content,userId:s.userId,username:s.username,avatar:s.avatar,timestamp:s.timestamp,channelId:s.channelId,selfId:s.selfId,elements:s.elements,isBot:s.type==="bot",quote:s.quote}));return o.sort((s,i)=>s.timestamp-i.timestamp),u.value.messages[n]=o,U.value[n]=o.length,u.value={...u.value},true}else return console.warn("获取历史消息失败:",a.error),false}catch(a){return console.error("获取历史消息时出错:",a),false}}function da(e){if(!q.value||e.touches.length!==1)return;const t=e.touches[0];H.value={x:t.clientX,y:t.clientY,time:Date.now()},ne.value={x:t.clientX,y:t.clientY},Be.value=false}function fa(e){if(!q.value||!H.value||e.touches.length!==1)return;const t=e.touches[0];ne.value={x:t.clientX,y:t.clientY};const a=t.clientX-H.value.x,n=t.clientY-H.value.y;if(Math.abs(a)>Math.abs(n)&&Math.abs(a)>30){const o=a>0,s=W.value==="messages"||W.value==="channels";if(o&&s){Be.value=true;const i=Math.min(a,200),c=150;i>c?he.value={show:true,text:"松开返回"}:he.value={show:true,text:`滑动返回 ${Math.round(i/c*100)}%`},e.preventDefault()}else he.value={show:false,text:""}}else he.value={show:false,text:""}}function ha(e){if(!q.value||!H.value)return;const a=Date.now()-H.value.time;if(ne.value){const n=ne.value.x-H.value.x,o=ne.value.y-H.value.y,s=n>150,i=Math.abs(n)>Math.abs(o),c=a<300&&n>80;(s&&i||c)&&ma()}H.value=null,ne.value=null,Be.value=false,he.value={show:false,text:""}}function ma(){switch(W.value){case"messages":W.value="channels";break;case"channels":W.value="bots",g.value="",S.value="";break}}function nt(){q.value=window.innerWidth<=768}function kt(){return!se.value||Ke()}const bt=()=>{q.value&&D.value&&ye(()=>{kt()&&ge()})},va=()=>{q.value&&setTimeout(()=>{D.value&&kt()&&ge()},300)};return St(L,(e,t)=>{t.length===0&&e.length>0&&ye(()=>{ge()})}),st(async()=>{nt(),window.addEventListener("resize",nt),window.visualViewport&&window.visualViewport.addEventListener("resize",bt),document.addEventListener("click",Ee),await ta()?(console.log("IndexedDB初始化成功"),setTimeout(async()=>{await et()},2e3),setInterval(async()=>{await et()},5*60*1e3)):console.warn("IndexedDB初始化失败,图片缓存功能将不可用"),await ua(),await ca(),ye(()=>{It()});const t=lt("chat-message-event",xt),a=lt("bot-message-sent-event",ra),n=lt("chat-bot-message-event",la);St(S,o=>{o&&ye(()=>{D.value&&(D.value.removeEventListener("scroll",Me),D.value.addEventListener("scroll",Me),Me()),!q.value&&me.value&&me.value.focus()})},{immediate:true}),setInterval(()=>{Je()},2*60*1e3),ga(()=>{window.removeEventListener("resize",nt),window.visualViewport&&window.visualViewport.removeEventListener("resize",bt),document.removeEventListener("click",Ee),t&&typeof t=="function"&&t(),a&&typeof a=="function"&&a(),n&&typeof n=="function"&&n(),D.value&&D.value.removeEventListener("scroll",Me),Object.values(b.value).forEach(o=>{URL.revokeObjectURL(o)}),b.value={},I&&(I.close(),I=null)})}),{AvatarComponent:ce,ImageComponent:Y,JsonCardComponent:pe,ForwardMessageComponent:Z,MessageElement:ke,chatData:u,channelMessageCounts:U,pluginConfig:ie,selectedBot:g,selectedChannel:S,inputMessage:Se,imageBlobUrls:b,pinnedBots:J,pinnedChannels:re,uploadedImages:V,showActionMenu:fe,isMobile:q,mobileView:W,touchStart:H,touchCurrent:ne,isSwipeActive:Be,swipeIndicator:he,messageHistory:D,messageInput:me,showScrollButton:$e,isUserScrolling:se,isSending:ve,draggingChannel:oe,dragStartPos:j,dragCurrentPos:A,dragElementInitialPos:De,dragOffset:Ie,dragThreshold:X,isDragReady:Q,draggedBubbleElement:C,contextMenu:N,fileInput:Te,bots:m,currentChannels:l,currentMessages:L,currentChannelName:Ue,currentChannelKey:_t,canSendMessage:ct,canInputMessage:Lt,mobileViewClass:Tt,inputPlaceholder:qt,chatContainerStyle:Ut,selectBot:Mt,selectChannel:Nt,handleBotRightClick:Kt,handleChannelRightClick:jt,showContextMenu:Ge,hideContextMenu:G,handleKeyDown:Ze,toggleBotPin:At,toggleChannelPin:zt,deleteBotMessages:Pt,deleteChannelMessages:Rt,sendMessage:Ot,toggleActionMenu:Ft,triggerImageUpload:Ht,handleFileSelect:Xt,handlePaste:Yt,uploadImage:Qe,removeImage:Vt,fileToBase64:dt,handleClickOutside:Ee,formatTime:Wt,getChannelTypeText:Jt,scrollToBottom:ge,checkScrollPosition:Me,isNearBottom:Ke,getChannelMessageCount:ft,startDrag:Gt,handleDragMove:je,handleDragEnd:Ae,resetDragState:ze,getDragStyle:Zt,getDragDistance:Qt,clearChannelHistory:ht,showNotification:T,createThresholdCircle:mt,removeThresholdCircle:vt,handleTouchStart:da,handleTouchMove:fa,handleTouchEnd:ha,handleInputFocus:va,getCachedImageUrl:Ve,cacheImage:xe,clearChannelImageCache:Pe,getMemoryStats:sa,getCacheStats:oa,isFileUrl:te,loadHistoryMessages:Ct,handleMessageEvent:xt,saveSelectionState:at,restoreSelectionState:It}}const ba={class:"bot-list"},Sa={class:"bot-items"},Ba=["onClick","onContextmenu"],$a={class:"bot-avatar"},Da={key:1,class:"avatar-placeholder"},_a={class:"bot-info"},La={class:"bot-name"},Ta={class:"bot-platform"},qa={class:"channel-list"},Ua={key:0,class:"empty-state"},Ma={key:1,class:"channel-items"},Ka=["data-channel-id","onClick","onContextmenu"],ja={class:"channel-info"},Aa={class:"channel-name"},za={class:"channel-type"},Pa=["onMousedown","onTouchstart","title"],Ra={class:"message-area"},Na={class:"panel-header"},Oa={key:0,class:"empty-state"},Fa={key:1,class:"message-content"},Ha={class:"message-avatar"},Xa={key:1,class:"avatar-placeholder"},Ya={class:"message-content-wrapper"},Va={class:"message-header"},Wa={class:"message-username"},Ja={class:"message-time"},Ga={key:0,class:"message-quote"},Za={class:"quote-header"},Qa={class:"quote-avatar"},Ea={key:1,class:"avatar-placeholder"},en={class:"quote-username"},tn={class:"quote-time"},an={class:"quote-content"},nn={class:"message-text"},sn={class:"message-input"},on={key:0,class:"image-preview-container"},rn=["src","alt"],ln=["onClick"],cn={class:"input-row"},un={class:"input-actions"},dn=["placeholder","disabled"],fn=["disabled"],hn=Ce({__name:"index",setup(te){const ce=ka(),{AvatarComponent:Y,MessageElement:pe,selectedBot:Z,selectedChannel:ke,inputMessage:u,pinnedBots:U,pinnedChannels:ie,uploadedImages:b,showActionMenu:be,swipeIndicator:ue,messageHistory:we,messageInput:I,showScrollButton:Ne,isSending:Oe,draggingChannel:$,dragThreshold:ae,contextMenu:M,fileInput:de,bots:Le,currentChannels:Fe,currentMessages:We,currentChannelName:F,currentChannelKey:K,canSendMessage:He,canInputMessage:g,mobileViewClass:S,inputPlaceholder:Se,chatContainerStyle:V,selectBot:fe,selectChannel:Te,handleBotRightClick:q,handleChannelRightClick:W,toggleBotPin:H,toggleChannelPin:ne,deleteBotMessages:Be,deleteChannelMessages:he,sendMessage:D,toggleActionMenu:me,triggerImageUpload:$e,handleFileSelect:se,handlePaste:ve,removeImage:oe,formatTime:j,getChannelTypeText:A,scrollToBottom:De,getChannelMessageCount:Ie,startDrag:X,getDragStyle:qe,getDragDistance:R,handleTouchStart:Q,handleTouchMove:C,handleTouchEnd:N,handleInputFocus:J}=ce;return(re,m)=>(y(),x("div",{class:le(["chat-container",r(S)]),style:ot(r(V)),onTouchstart:m[15]||(m[15]=(...l)=>r(Q)&&r(Q)(...l)),onTouchmove:m[16]||(m[16]=(...l)=>r(C)&&r(C)(...l)),onTouchend:m[17]||(m[17]=(...l)=>r(N)&&r(N)(...l))},[B(" 左侧机器人列表 "),f("div",ba,[m[18]||(m[18]=f("div",{class:"panel-header"},[f("h3",null,"机器人")],-1)),f("div",Sa,[(y(true),x(ee,null,_e(r(Le),l=>(y(),x("div",{key:l.selfId,class:le(["bot-item",{active:r(Z)===l.selfId,pinned:r(U).has(l.selfId)}]),onClick:L=>r(fe)(l.selfId),onContextmenu:L=>r(q)(L,l.selfId)},[f("div",$a,[l.avatar?(y(),Re(r(Y),{key:0,src:l.avatar,alt:l.username,"channel-key":"bot-list"},null,8,["src","alt"])):(y(),x("div",Da,_(l.username.charAt(0).toUpperCase()),1))]),f("div",_a,[f("div",La,_(l.username),1),f("div",Ta,_(l.platform),1)]),f("div",{class:le(["bot-status",l.status])},null,2)],42,Ba))),128))])]),B(" 中间频道列表 "),f("div",qa,[m[19]||(m[19]=f("div",{class:"panel-header"},[f("h3",null,"频道")],-1)),r(Z)?(y(),x("div",Ma,[(y(true),x(ee,null,_e(r(Fe),l=>(y(),x("div",{key:l.id,class:le(["channel-item",{active:r(ke)===l.id,pinned:r(ie).has(`${r(Z)}:${l.id}`)}]),"data-channel-id":l.id,onClick:L=>r(Te)(l.id),onContextmenu:L=>r(W)(L,l.id)},[f("div",ja,[f("div",Aa,_(l.name),1),f("div",za,_(r(A)(l.type)),1)]),r(Ie)(l.id)>0?(y(),x("div",{key:0,class:le(["channel-message-count draggable-bubble",{dragging:r($)===l.id,"will-delete":r($)===l.id&&r(R)(l.id)>r(ae)}]),onMousedown:L=>r(X)(L,l.id),onTouchstart:L=>r(X)(L,l.id),style:ot(r(qe)(l.id)),title:r($)===l.id?r(R)(l.id)>r(ae)?"松开清理历史记录":"拖拽更远以清理历史记录":"拖拽清理历史记录"},_(r(Ie)(l.id)),47,Pa)):B("v-if",true)],42,Ka))),128))])):(y(),x("div",Ua," 请选择一个机器人 "))]),B(" 右侧消息区域 "),f("div",Ra,[f("div",Na,[f("h3",null,_(r(F)||"选择频道"),1)]),!r(Z)||!r(ke)?(y(),x("div",Oa," 请选择机器人和频道 ")):(y(),x("div",Fa,[B(" 消息历史 "),f("div",{class:"message-history",ref_key:"messageHistory",ref:we},[(y(true),x(ee,null,_e(r(We),l=>(y(),x("div",{key:l.id,class:le(["message-item",{"bot-message":l.isBot}])},[f("div",Ha,[l.avatar?(y(),Re(r(Y),{key:0,src:l.avatar,alt:l.username,"channel-key":r(K)},null,8,["src","alt","channel-key"])):(y(),x("div",Xa,_(l.username.charAt(0).toUpperCase()),1))]),f("div",Ya,[f("div",Va,[f("span",Wa,_(l.username),1),f("span",Ja,_(r(j)(l.timestamp)),1)]),B(" 引用消息显示 "),l.quote?(y(),x("div",Ga,[f("div",Za,[f("div",Qa,[l.quote.user.avatar?(y(),Re(r(Y),{key:0,src:l.quote.user.avatar,alt:l.quote.user.username,"channel-key":r(K)},null,8,["src","alt","channel-key"])):(y(),x("div",Ea,_(l.quote.user.username.charAt(0).toUpperCase()),1))]),f("span",en,_(l.quote.user.username),1),f("span",tn,_(r(j)(l.quote.timestamp)),1)]),f("div",an,[l.quote.elements&&l.quote.elements.length>0?(y(true),x(ee,{key:0},_e(l.quote.elements,(L,Ue)=>(y(),Re(r(pe),{key:`quote-${Ue}`,element:L,"channel-key":r(K)},null,8,["element","channel-key"]))),128)):(y(),x(ee,{key:1},[rt(_(l.quote.content),1)],64))])])):B("v-if",true),f("div",nn,[l.elements&&l.elements.length>0?(y(true),x(ee,{key:0},_e(l.elements,(L,Ue)=>(y(),Re(r(pe),{key:Ue,element:L,"channel-key":r(K)},null,8,["element","channel-key"]))),128)):(y(),x(ee,{key:1},[rt(_(l.content),1)],64))])])],2))),128))],512),B(" 悬浮的滚动到底部按钮 "),Bt(f("div",{class:"floating-scroll-button",onClick:m[0]||(m[0]=(...l)=>r(De)&&r(De)(...l))},m[20]||(m[20]=[f("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},[f("path",{d:"M7 10l5 5 5-5z"})],-1)]),512),[[ya,r(Ne)]]),B(" 输入框 "),f("div",sn,[B(" 图片预览区域 "),r(b).length>0?(y(),x("div",on,[(y(true),x(ee,null,_e(r(b),l=>(y(),x("div",{key:l.tempId,class:"image-preview-item"},[f("img",{src:l.preview,alt:l.filename,class:"preview-image"},null,8,rn),f("button",{class:"remove-image-btn",onClick:L=>r(oe)(l.tempId),title:"删除图片"},m[21]||(m[21]=[f("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"currentColor"},[f("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"})],-1)]),8,ln)]))),128))])):B("v-if",true),f("div",cn,[B(" 加号按钮 "),f("div",un,[f("button",{class:le(["add-button",{active:r(be)}]),onClick:m[1]||(m[1]=(...l)=>r(me)&&r(me)(...l)),title:"更多操作"},m[22]||(m[22]=[f("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2.5","stroke-linecap":"round","stroke-linejoin":"round"},[f("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),f("line",{x1:"5",y1:"12",x2:"19",y2:"12"})],-1)]),2),B(" 操作菜单 "),r(be)?(y(),x("div",{key:0,class:"action-menu",onClick:m[3]||(m[3]=$t(()=>{},["stop"]))},[f("button",{class:"action-menu-item",onClick:m[2]||(m[2]=(...l)=>r($e)&&r($e)(...l))},m[23]||(m[23]=[f("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[f("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),f("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),f("polyline",{points:"21,15 16,10 5,21"})],-1),rt(" 上传图片 ",-1)]))])):B("v-if",true)]),Bt(f("input",{"onUpdate:modelValue":m[4]||(m[4]=l=>wa(u)?u.value=l:null),type:"text",placeholder:r(Se),onKeyup:m[5]||(m[5]=pa((...l)=>r(D)&&r(D)(...l),["enter"])),disabled:!r(g),ref_key:"messageInput",ref:I,onPaste:m[6]||(m[6]=(...l)=>r(ve)&&r(ve)(...l)),onFocus:m[7]||(m[7]=(...l)=>r(J)&&r(J)(...l))},null,40,dn),[[Ia,r(u)]]),f("button",{onClick:m[8]||(m[8]=(...l)=>r(D)&&r(D)(...l)),disabled:!r(He),class:le({"is-sending":r(Oe)})},_(r(Oe)?"发送中...":"发送"),11,fn)]),B(" 隐藏的文件输入 "),f("input",{type:"file",ref_key:"fileInput",ref:de,onChange:m[9]||(m[9]=(...l)=>r(se)&&r(se)(...l)),accept:"image/*",multiple:"",style:{display:"none"}},null,544)])]))]),B(" 右键菜单 "),r(M).show?(y(),x("div",{key:0,class:"context-menu",style:ot({left:r(M).x+"px",top:r(M).y+"px"}),onClick:m[14]||(m[14]=$t(()=>{},["stop"]))},[B(" 机器人右键菜单 "),r(M).type==="bot"?(y(),x(ee,{key:0},[f("div",{class:"context-menu-item",onClick:m[10]||(m[10]=l=>r(H)(r(M).targetId))},_(r(U).has(r(M).targetId)?"取消置顶":"置顶"),1),f("div",{class:"context-menu-item danger",onClick:m[11]||(m[11]=l=>r(Be)(r(M).targetId))}," 彻底删除此机器人所有数据 ")],64)):B("v-if",true),B(" 频道右键菜单 "),r(M).type==="channel"?(y(),x(ee,{key:1},[f("div",{class:"context-menu-item",onClick:m[12]||(m[12]=l=>r(ne)(r(M).targetId))},_(r(ie).has(`${r(Z)}:${r(M).targetId}`)?"取消置顶":"置顶"),1),f("div",{class:"context-menu-item danger",onClick:m[13]||(m[13]=l=>r(he)(r(M).targetId))}," 彻底删除此频道所有数据 ")],64)):B("v-if",true)],4)):B("v-if",true),B(" 滑动指示器 "),f("div",{class:le(["swipe-indicator",{show:r(ue).show}])},_(r(ue).text),3)],38))}}),Dt=(te,ce)=>{const Y=te.__vccOpts||te;for(const[pe,Z]of ce)Y[pe]=Z;return Y},mn=Dt(hn,[["__scopeId","data-v-de93bb69"]]),vn={},gn={class:"k-icon",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none"};function yn(te,ce){return y(),x("svg",gn,ce[0]||(ce[0]=[f("path",{d:"M8 10.5H16",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),f("path",{d:"M8 14H13.5",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),f("path",{d:"M17 3.33782C15.5291 2.48697 13.8214 2 12 2C6.47715 2 2 6.47715 2 12C2 13.5997 2.37562 15.1116 3.04346 16.4525C3.22094 16.8088 3.28001 17.2161 3.17712 17.6006L2.58151 19.8267C2.32295 20.793 3.20701 21.677 4.17335 21.4185L6.39939 20.8229C6.78393 20.72 7.19121 20.7791 7.54753 20.9565C8.88837 21.6244 10.4003 22 12 22C17.5228 22 22 17.5228 22 12C22 10.1786 21.513 8.47087 20.6622 7",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1)]))}const pn=Dt(vn,[["render",yn]]);Ca.register("activity:chat",pn);const xn=te=>{te.page({name:"聊天室",path:"/chat-patch",desc:"",authority:4,icon:"activity:chat",component:Ce({setup(){return()=>h(xa("k-layout"),{},{default:()=>h(mn)})}})})};export{xn as default};
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .message-quote[data-v-de93bb69]{margin:8px 0;padding:8px 12px;background-color:#bebebe1a;border-left:4px solid rgba(151,152,152,.45);border-radius:6px;font-size:.9em;position:relative}.quote-indicator[data-v-de93bb69]{font-size:.75em;color:#007bff;font-weight:600;margin-bottom:4px;text-transform:uppercase}.quote-header[data-v-de93bb69]{display:flex;align-items:center;margin-bottom:4px;gap:6px}.quote-avatar[data-v-de93bb69]{width:20px;height:20px;border-radius:50%;overflow:hidden;flex-shrink:0}.quote-avatar img[data-v-de93bb69]{width:100%;height:100%;object-fit:cover}.quote-avatar .avatar-placeholder[data-v-de93bb69]{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background-color:#6c757d;color:#fff;font-size:10px;font-weight:700}.quote-username[data-v-de93bb69]{font-weight:600;color:#007bff;font-size:.85em}.quote-time[data-v-de93bb69]{color:#6c757d;font-size:.75em;margin-left:auto}.quote-content[data-v-de93bb69]{color:#7276b7;line-height:1.3;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto}.quote-content .message-image[data-v-de93bb69]{max-width:min(200px,50vw);max-height:100px}.quote-content .message-image-container[data-v-de93bb69]{margin:2px 0}@media (prefers-color-scheme:dark){.message-quote[data-v-de93bb69]{background-color:#ffffff14;border-left-color:#0d6efd}.quote-content[data-v-de93bb69]{color:#adb5bd}.quote-username[data-v-de93bb69]{color:#0d6efd}}.chat-container[data-v-de93bb69]{display:flex;height:100vh;background:0 0;margin-left:0;width:100%;overflow:hidden;color:inherit;position:relative}.bot-list[data-v-de93bb69],.channel-list[data-v-de93bb69],.message-area[data-v-de93bb69]{display:flex;flex-direction:column;background:0 0;border-right:1px solid rgba(128,128,128,.2)}.bot-list[data-v-de93bb69]{width:250px;min-width:250px;max-width:250px;flex-shrink:0}.channel-list[data-v-de93bb69]{width:300px;min-width:300px;max-width:300px;flex-shrink:0}.message-area[data-v-de93bb69]{flex:1;border-right:none}.panel-header[data-v-de93bb69]{padding:16px;border-bottom:1px solid rgba(128,128,128,.2);background:0 0;display:flex;align-items:center;justify-content:space-between}.panel-header h3[data-v-de93bb69]{margin:0;font-size:16px;font-weight:600;color:currentColor}.back-button[data-v-de93bb69]{display:none;background:0 0;border:none;color:currentColor;font-size:18px;cursor:pointer;padding:4px 8px;border-radius:4px;transition:background-color .2s}.back-button[data-v-de93bb69]:hover{background:#8080801a}.bot-items[data-v-de93bb69],.channel-items[data-v-de93bb69]{flex:1;overflow-y:auto;max-height:calc(100vh - 60px)}.bot-item[data-v-de93bb69],.channel-item[data-v-de93bb69]{display:flex;align-items:center;padding:12px 16px;cursor:pointer;border-bottom:1px solid rgba(128,128,128,.1);transition:background-color .2s}.bot-item[data-v-de93bb69]:hover,.channel-item[data-v-de93bb69]:hover{background:#8080801a}.bot-item.active[data-v-de93bb69],.channel-item.active[data-v-de93bb69]{background:#2196f31a;border-right:3px solid #2196f3}.bot-avatar[data-v-de93bb69]{width:40px;height:40px;margin-right:12px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;background:#e0e0e0}.bot-avatar img[data-v-de93bb69]{width:100%;height:100%;object-fit:cover}.avatar-placeholder[data-v-de93bb69]{font-size:16px;font-weight:700;color:currentColor;opacity:.7}.bot-info[data-v-de93bb69]{flex:1}.bot-name[data-v-de93bb69]{font-weight:500;color:currentColor;margin-bottom:2px}.bot-platform[data-v-de93bb69]{font-size:12px;color:currentColor;opacity:.7}.bot-status[data-v-de93bb69]{width:8px;height:8px;border-radius:50%;margin-left:8px}.bot-status.online[data-v-de93bb69]{background:#4caf50}.bot-status.offline[data-v-de93bb69]{background:#f44336}.channel-info[data-v-de93bb69]{flex:1}.channel-name[data-v-de93bb69]{font-weight:500;color:currentColor;margin-bottom:2px}.channel-type[data-v-de93bb69]{font-size:12px;color:currentColor;opacity:.7}.channel-message-count[data-v-de93bb69]{background:#2196f3;color:#fff;font-size:12px;padding:2px 6px;border-radius:10px;min-width:18px;text-align:center;position:relative;transition:all .2s ease}.channel-message-count.draggable-bubble[data-v-de93bb69]{cursor:grab;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.channel-message-count.draggable-bubble[data-v-de93bb69]:hover{background:#1976d2;transform:scale(1.1);box-shadow:0 2px 8px #2196f34d}.channel-message-count.draggable-bubble.dragging[data-v-de93bb69],.channel-message-count.draggable-bubble[data-v-de93bb69]:active{cursor:grabbing;background:#1565c0;box-shadow:0 4px 12px #2196f366}.dragging-clone[data-v-de93bb69]{position:fixed;z-index:1000;pointer-events:none;transition:none;box-sizing:border-box;display:flex;align-items:center;justify-content:center;background:#2196f3;color:#fff;font-size:12px;padding:2px 6px;border-radius:10px;min-width:18px;text-align:center;box-shadow:0 4px 12px #2196f366}.dragging-clone.will-delete[data-v-de93bb69]{background:#f44336!important;animation:shake-de93bb69 .3s ease-in-out infinite}@keyframes pulseThreshold-de93bb69{0%,to{opacity:.4;transform:scale(.9);border-color:#f4433699;box-shadow:0 0 15px #f4433633}50%{opacity:.8;transform:scale(1.1);border-color:#f44336;box-shadow:0 0 25px #f4433666}}@keyframes menuSlideIn-de93bb69{0%{transform:translateY(8px);opacity:0}to{transform:translateY(0);opacity:1}}.message-content[data-v-de93bb69]{display:flex;flex-direction:column;height:calc(100vh - 60px);overflow:hidden;position:relative}.message-history[data-v-de93bb69]{flex:1;overflow-y:auto;padding:16px 16px 8px;max-height:calc(100vh - 200px)}.message-item[data-v-de93bb69]{display:flex;margin-bottom:16px;padding:8px;border-radius:8px;transition:background-color .3s ease}.message-item[data-v-de93bb69]:hover{background-color:#8080801a}.message-item.new-message[data-v-de93bb69]{background-color:#4caf5033;animation:highlight-de93bb69 2s ease-out}.message-item.bot-message[data-v-de93bb69]{flex-direction:row-reverse;justify-content:flex-start}.message-item.bot-message .message-avatar[data-v-de93bb69]{margin-right:0;margin-left:12px}.message-item.bot-message .message-content-wrapper[data-v-de93bb69]{display:flex;flex-direction:column;align-items:flex-end}.message-item.bot-message .message-header[data-v-de93bb69]{display:flex;align-items:center;justify-content:flex-end;margin-bottom:4px}.message-item.bot-message .message-username[data-v-de93bb69]{margin-right:0;margin-left:8px;order:2}.message-item.bot-message .message-time[data-v-de93bb69]{order:1}.message-item.bot-message .message-text[data-v-de93bb69]{background-color:#2196f31a;padding:8px 12px;border-radius:12px 12px 4px;display:inline-block;max-width:80%;text-align:left;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere}@keyframes highlight-de93bb69{0%{background-color:#4caf504d}to{background-color:transparent}}.message-avatar[data-v-de93bb69]{width:32px;height:32px;margin-right:12px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;background:#e0e0e0;flex-shrink:0}.message-avatar img[data-v-de93bb69]{width:100%;height:100%;object-fit:cover}.message-avatar .avatar-placeholder[data-v-de93bb69]{font-size:12px;font-weight:700;color:currentColor;opacity:.7}.message-content-wrapper[data-v-de93bb69]{flex:1}.message-header[data-v-de93bb69]{display:flex;align-items:center;margin-bottom:4px}.message-username[data-v-de93bb69]{font-weight:500;color:currentColor;margin-right:8px}.message-time[data-v-de93bb69]{font-size:12px;color:currentColor;opacity:.5}.message-text[data-v-de93bb69]{color:currentColor;line-height:1.4;word-wrap:break-word;word-break:break-all;white-space:pre-wrap;max-width:100%;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto}.message-item:not(.bot-message) .message-text[data-v-de93bb69]{background-color:#8080801a;padding:8px 12px;border-radius:12px 12px 12px 4px;display:inline-block;max-width:80%;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere}.message-input[data-v-de93bb69]{display:flex;flex-direction:column;padding:12px 16px 16px;border-top:1px solid rgba(128,128,128,.2);background:0 0;flex-shrink:0;position:sticky;bottom:0;margin-top:-10px}.input-row[data-v-de93bb69]{display:flex;gap:8px;align-items:center}.floating-scroll-button[data-v-de93bb69]{position:absolute;right:24px;bottom:18%;width:48px;height:48px;background:#2196f3;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 12px #2196f34d;color:#fff;transition:all .3s ease;z-index:100;border:2px solid rgba(255,255,255,.2)}.floating-scroll-button[data-v-de93bb69]:hover{background:#1976d2;transform:scale(1.1);box-shadow:0 6px 16px #2196f366}.floating-scroll-button[data-v-de93bb69]:active{transform:scale(.95)}.input-row button[data-v-de93bb69]{padding:8px 16px;background:#2196f3;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s}.message-image-container[data-v-de93bb69]{margin:8px 0;max-width:100%;display:block}.message-image[data-v-de93bb69]{border-radius:8px;object-fit:contain;display:block;cursor:pointer;transition:transform .2s ease;max-width:min(400px,66.67vw);max-height:200px;width:auto;height:auto}.message-image-loading[data-v-de93bb69]{display:inline-block;padding:8px 12px;background:#8080801a;border-radius:4px;color:currentColor;opacity:.7;font-size:12px}.message-image-error[data-v-de93bb69]{display:inline-block;padding:8px 12px;background:#f443361a;border:1px solid rgba(244,67,54,.3);border-radius:4px;color:#f44336;font-size:12px;max-width:300px;word-break:break-word}.message-paragraph[data-v-de93bb69]{display:block;margin-bottom:4px}.message-paragraph[data-v-de93bb69]:last-child{margin-bottom:0}.forward-message-container[data-v-de93bb69]{border:1px solid #fff;border-radius:8px;margin:4px 0;overflow:hidden;background:#f9f9f900}.forward-message-preview[data-v-de93bb69]{padding:12px;cursor:pointer;transition:background-color .2s}.forward-message-preview[data-v-de93bb69]:hover{background:#f0f0f0}.forward-message-title[data-v-de93bb69]{font-weight:600;color:#333;margin-bottom:8px;font-size:14px}.forward-message-preview-item[data-v-de93bb69]{color:#666;font-size:13px;margin:2px 0;line-height:1.4;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere}.forward-message-footer[data-v-de93bb69]{display:flex;justify-content:space-between;align-items:center;margin-top:8px;padding-top:8px;border-top:1px solid #e8e8e8}.forward-message-count[data-v-de93bb69]{color:#2196f3;font-size:12px}.forward-message-toggle[data-v-de93bb69]{color:#666;font-size:12px}.forward-message-expanded[data-v-de93bb69]{border-top:1px solid #e0e0e0;background:#fff;max-height:400px;overflow-y:auto}.forwarded-message-item[data-v-de93bb69]{padding:12px;border-bottom:1px solid #f0f0f0}.forwarded-message-item[data-v-de93bb69]:last-child{border-bottom:none}.forwarded-message-header[data-v-de93bb69]{display:flex;align-items:center;margin-bottom:6px}.forwarded-message-nickname[data-v-de93bb69]{font-weight:600;color:#333;font-size:13px}.forwarded-message-userid[data-v-de93bb69]{color:#999;font-size:11px;margin-left:6px}.forwarded-message-content[data-v-de93bb69]{color:#555;font-size:13px;line-height:1.4;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere}.message-at[data-v-de93bb69]{background:#2196f31a;color:#2196f3;padding:2px 4px;border-radius:3px;font-weight:500;cursor:pointer}.message-unknown[data-v-de93bb69]{background:#ff98001a;color:#ff9800;padding:2px 4px;border-radius:3px;font-style:italic;cursor:help}.input-row input[data-v-de93bb69]{flex:1;min-width:0;padding:8px 12px;border:1px solid rgba(128,128,128,.3);border-radius:4px;outline:0;background:0 0;color:currentColor}.input-row input[data-v-de93bb69]:focus{border-color:#2196f3;box-shadow:0 0 0 2px #2196f333}.input-row input[data-v-de93bb69]::placeholder{color:currentColor;opacity:.5}.input-row button[data-v-de93bb69]{padding:8px 16px;background:#2196f3;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;flex-shrink:0;white-space:nowrap}.input-row button[data-v-de93bb69]:hover:not(:disabled){background:#1976d2}.input-row button[data-v-de93bb69]:disabled{background:#8080804d;cursor:not-allowed}.input-row button.is-sending[data-v-de93bb69]{background:#ffc107!important;color:#333!important;cursor:default!important}.message-input .input-row button.is-sending[data-v-de93bb69]{background:#ffc107!important;color:#333!important;cursor:default!important;border-color:#ffc107!important}.empty-state[data-v-de93bb69]{display:flex;align-items:center;justify-content:center;height:100%;color:currentColor;opacity:.5;font-size:14px}.message-text-content[data-v-de93bb69]{display:inline;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto}.message-image-container[data-v-de93bb69]{display:block;margin:4px 0}.message-image[data-v-de93bb69]{border-radius:8px;margin:4px 0;display:block;cursor:pointer;transition:transform .2s ease;object-fit:contain;background:#8080801a}.message-image[data-v-de93bb69]:hover{transform:scale(1.02)}.message-image-loading[data-v-de93bb69]{height:60px;width:200px;border-radius:8px;margin:4px 0;display:flex;align-items:center;justify-content:center;background:#8080801a;color:currentColor;opacity:.7;font-size:14px;border:1px dashed rgba(128,128,128,.3)}.message-image-error[data-v-de93bb69]{min-height:60px;width:200px;border-radius:8px;margin:4px 0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#8080801a;color:currentColor;opacity:.7;font-size:14px;border:1px dashed rgba(128,128,128,.3);padding:8px;text-align:center}.message-at[data-v-de93bb69]{background:#2196f31a;color:#2196f3;padding:2px 6px;border-radius:4px;font-weight:500;cursor:pointer;display:inline-block;margin:0 2px}.message-at[data-v-de93bb69]:hover{background:#2196f333}.message-unknown[data-v-de93bb69]{background:#ff98001a;color:#ff9800;padding:2px 6px;border-radius:4px;font-size:12px;display:inline-block;margin:0 2px;cursor:help}@keyframes pulse-de93bb69{0%,to{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.1)}}.channel-message-count.will-delete[data-v-de93bb69]{background:#f44336!important;animation:shake-de93bb69 .3s ease-in-out infinite}@keyframes shake-de93bb69{0%,to{transform:translate(0)}25%{transform:translate(-2px)}75%{transform:translate(2px)}}body.dragging-bubble-global[data-v-de93bb69]{user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;cursor:grabbing}.drag-threshold-circle[data-v-de93bb69]{position:fixed;pointer-events:none;border:3px dashed rgba(244,67,54,.8);border-radius:50%;z-index:999;background:#f443361a;box-shadow:0 0 20px #f443364d;animation:pulseThreshold-de93bb69 1.5s ease-in-out infinite}.context-menu[data-v-de93bb69]{position:fixed;background:#ffffffa6;border:1px solid rgba(0,0,0,.1);border-radius:8px;box-shadow:0 8px 32px #00000026;z-index:10000;min-width:180px;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);overflow:hidden}.context-menu-item[data-v-de93bb69]{padding:12px 16px;cursor:pointer;color:#333;font-size:14px;font-weight:500;transition:all .2s ease;border-bottom:1px solid rgba(0,0,0,.08);position:relative}.context-menu-item[data-v-de93bb69]:last-child{border-bottom:none}.context-menu-item[data-v-de93bb69]:hover{background:#2196f31a;color:#1976d2;transform:translate(2px)}.context-menu-item.danger[data-v-de93bb69]{color:#d32f2f}.context-menu-item.danger[data-v-de93bb69]:hover{background:#f443361a;color:#c62828}.bot-item.pinned[data-v-de93bb69],.channel-item.pinned[data-v-de93bb69]{background:#ffc1071a;border-left:3px solid #ffc107}.bot-item.pinned[data-v-de93bb69]:before,.channel-item.pinned[data-v-de93bb69]:before{content:"📌";position:absolute;left:4px;top:50%;transform:translateY(-50%);font-size:12px;opacity:.7}.bot-item.pinned[data-v-de93bb69],.channel-item.pinned[data-v-de93bb69]{position:relative;padding-left:24px}@media (prefers-color-scheme:dark){.context-menu[data-v-de93bb69]{background:#ffffff26;border-color:#fff3;box-shadow:0 8px 32px #0006}.context-menu-item[data-v-de93bb69]{color:#fff;border-bottom-color:#ffffff1a}.context-menu-item[data-v-de93bb69]:hover{background:#2196f333;color:#64b5f6}.context-menu-item.danger[data-v-de93bb69]{color:#ff8a80}.context-menu-item.danger[data-v-de93bb69]:hover{background:#f4433633;color:#ffab91}.bot-item.pinned[data-v-de93bb69],.channel-item.pinned[data-v-de93bb69]{background:#ffc10726}}.message-share-card[data-v-de93bb69]{display:inline-block;width:75px;margin:8px 0;border:1px solid rgba(128,128,128,.2);border-radius:12px;background:#ffffff0d;transition:all .3s ease;cursor:pointer;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.message-share-card[data-v-de93bb69]:hover{transform:translateY(-2px);box-shadow:0 8px 24px #00000026;border-color:#2196f34d}.share-card-preview[data-v-de93bb69]{width:100%;position:relative;display:flex;align-items:center;justify-content:center;padding:4px;border-radius:12px 12px 0 0}.share-card-image[data-v-de93bb69]{max-width:calc(100% - 8px);width:auto;height:auto;object-fit:contain;transition:transform .3s ease;display:block;border-radius:4px}.message-share-card:hover .share-card-image[data-v-de93bb69]{transform:scale(1.05)}.share-card-content[data-v-de93bb69]{padding:8px}.share-card-header[data-v-de93bb69]{display:flex;align-items:center;margin-bottom:12px;gap:12px}.share-card-icon[data-v-de93bb69]{width:32px;height:32px;border-radius:8px;object-fit:cover;flex-shrink:0}.share-card-app-info[data-v-de93bb69]{flex:1;min-width:0}.share-card-app-name[data-v-de93bb69]{font-size:12px;color:currentColor;opacity:.7;margin-bottom:2px;font-weight:500}.share-card-title[data-v-de93bb69]{font-size:10px;font-weight:600;color:currentColor;line-height:1.2;word-wrap:break-word;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden}.share-card-desc[data-v-de93bb69]{font-size:14px;color:currentColor;opacity:.8;line-height:1.4;margin-bottom:12px;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;word-wrap:break-word}.share-card-link-hint[data-v-de93bb69]{font-size:12px;color:#2196f3;font-weight:500;display:flex;align-items:center;gap:4px}.share-card-link-hint[data-v-de93bb69]:after{content:"→";transition:transform .2s ease}.message-share-card:hover .share-card-link-hint[data-v-de93bb69]:after{transform:translate(2px)}.message-json-error[data-v-de93bb69],.message-json-raw[data-v-de93bb69]{display:inline-block;margin:8px 0;max-width:400px}.json-error-text[data-v-de93bb69]{color:#f44336;font-size:14px;font-weight:500}.json-label[data-v-de93bb69]{color:currentColor;opacity:.7;font-size:12px;font-weight:500;margin-bottom:8px}.json-raw-data[data-v-de93bb69]{margin-top:8px}.json-raw-data summary[data-v-de93bb69]{cursor:pointer;font-size:12px;color:#2196f3;font-weight:500;padding:4px 8px;border-radius:4px;background:#2196f31a;display:inline-block;transition:background-color .2s ease}.json-raw-data summary[data-v-de93bb69]:hover{background:#2196f333}.json-raw-content[data-v-de93bb69]{margin-top:8px;padding:12px;background:#8080801a;border-radius:8px;font-family:Courier New,monospace;font-size:12px;color:currentColor;opacity:.8;white-space:pre-wrap;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere;max-height:200px;overflow-y:auto;border:1px solid rgba(128,128,128,.2)}@media (prefers-color-scheme:dark){.message-share-card[data-v-de93bb69]{background:#ffffff14;border-color:#ffffff26}.message-share-card[data-v-de93bb69]:hover{border-color:#2196f380;box-shadow:0 8px 24px #0000004d}.json-raw-content[data-v-de93bb69]{background:#ffffff0d;border-color:#ffffff1a}}@media (max-width:768px){.chat-container[data-v-de93bb69]{position:relative;height:100vh;height:100dvh}.bot-list[data-v-de93bb69],.channel-list[data-v-de93bb69],.message-area[data-v-de93bb69]{position:absolute;top:0;left:0;width:100%;height:100%;transition:transform .3s ease;z-index:1}.bot-list[data-v-de93bb69]{transform:translate(0);z-index:3}.channel-list[data-v-de93bb69]{transform:translate(100%);z-index:2}.message-area[data-v-de93bb69]{transform:translate(200%);z-index:1}.chat-container.show-channels .bot-list[data-v-de93bb69]{transform:translate(-100%)}.chat-container.show-channels .channel-list[data-v-de93bb69]{transform:translate(0);z-index:3}.chat-container.show-channels .message-area[data-v-de93bb69]{transform:translate(100%)}.chat-container.show-messages .bot-list[data-v-de93bb69]{transform:translate(-200%)}.chat-container.show-messages .channel-list[data-v-de93bb69]{transform:translate(-100%)}.chat-container.show-messages .message-area[data-v-de93bb69]{transform:translate(0);z-index:3}.back-button[data-v-de93bb69]{display:none!important}.panel-header[data-v-de93bb69]{flex-direction:row-reverse;position:sticky;top:0;z-index:5;background:inherit}.panel-header h3[data-v-de93bb69]{text-align:right}.floating-scroll-button[data-v-de93bb69]{right:16px;bottom:calc(90px + env(safe-area-inset-bottom,0px));width:40px;height:40px;transition:bottom .3s ease}.message-input[data-v-de93bb69]{padding:8px 12px calc(12px + env(safe-area-inset-bottom,0px)) 12px;position:fixed;bottom:20px;left:0;right:0;background:inherit;border-top:1px solid rgba(128,128,128,.2);z-index:10;min-height:calc(60px + env(safe-area-inset-bottom,0px));transition:transform .3s ease;transform:translateZ(0)}.input-row input[data-v-de93bb69]{font-size:16px;padding:10px 12px}.input-row button[data-v-de93bb69]{padding:10px 16px;font-size:16px}.message-history[data-v-de93bb69]{padding:12px;max-height:calc(100vh - 140px - env(safe-area-inset-bottom,0px));max-height:calc(100dvh - 140px - env(safe-area-inset-bottom,0px));padding-bottom:calc(80px + env(safe-area-inset-bottom,0px));overflow-y:auto;-webkit-overflow-scrolling:touch;transition:max-height .3s ease}.message-item[data-v-de93bb69]{margin-bottom:12px;padding:6px}.message-text[data-v-de93bb69]{max-width:90%!important}.message-avatar[data-v-de93bb69]{width:28px;height:28px;margin-right:8px}.message-item.bot-message .message-avatar[data-v-de93bb69]{margin-left:8px}.message-image[data-v-de93bb69]{max-width:min(280px,66.67vw);max-height:160px}.quote-content .message-image[data-v-de93bb69]{max-width:min(150px,50vw);max-height:80px}.context-menu[data-v-de93bb69]{min-width:160px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}.context-menu-item[data-v-de93bb69]{padding:14px 16px;font-size:16px}.bot-item[data-v-de93bb69],.channel-item[data-v-de93bb69]{padding:14px 16px}.bot-avatar[data-v-de93bb69]{width:36px;height:36px;margin-right:10px}.bot-name[data-v-de93bb69],.channel-name[data-v-de93bb69]{font-size:15px}.bot-platform[data-v-de93bb69],.channel-type[data-v-de93bb69]{font-size:13px}}@media (min-width:769px) and (max-width:1024px){.bot-list[data-v-de93bb69]{width:220px;min-width:220px;max-width:220px}.channel-list[data-v-de93bb69]{width:280px;min-width:280px;max-width:280px}.message-image[data-v-de93bb69]{max-width:min(350px,66.67vw);max-height:180px}}.chat-container.swiping[data-v-de93bb69]{overflow:hidden}.bot-list.swiping[data-v-de93bb69],.channel-list.swiping[data-v-de93bb69],.message-area.swiping[data-v-de93bb69]{transition:none!important}.swipe-indicator[data-v-de93bb69]{position:fixed;top:50%;left:20px;transform:translateY(-50%);background:#2196f3cc;color:#fff;padding:8px 12px;border-radius:20px;font-size:14px;z-index:1000;opacity:0;transition:opacity .2s ease;pointer-events:none;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.swipe-indicator.show[data-v-de93bb69]{opacity:1}.message-area .message-content[data-v-de93bb69]{padding-bottom:80px}.image-preview-container[data-v-de93bb69]{display:flex;flex-wrap:wrap;gap:8px;padding:8px 0;margin-bottom:8px;border-bottom:1px solid rgba(128,128,128,.1)}.image-preview-item[data-v-de93bb69]{position:relative;width:60px;height:60px;border-radius:8px;overflow:hidden;border:2px solid rgba(33,150,243,.3);background:#8080801a}.preview-image[data-v-de93bb69]{width:100%;height:100%;object-fit:cover;display:block}.remove-image-btn[data-v-de93bb69]{position:absolute;top:-6px;right:-6px;width:20px;height:20px;border-radius:50%;background:#f44336;color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:12px;transition:all .2s ease;box-shadow:0 2px 4px #0003}.remove-image-btn[data-v-de93bb69]:hover{background:#d32f2f;transform:scale(1.1)}.input-actions[data-v-de93bb69]{position:relative;margin-right:8px}.add-button[data-v-de93bb69]{width:36px;height:36px;border-radius:12px;background:linear-gradient(135deg,#667eea 0,#764ba2);border:none;color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .3s cubic-bezier(.4,0,.2,1);flex-shrink:0;box-shadow:0 2px 8px #667eea4d;position:relative;overflow:hidden}.add-button[data-v-de93bb69]:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(135deg,#fff3 0,#ffffff1a);border-radius:12px;opacity:0;transition:opacity .3s ease}.add-button[data-v-de93bb69]:hover{transform:translateY(-2px) scale(1.05);box-shadow:0 4px 16px #667eea66}.add-button[data-v-de93bb69]:hover:before{opacity:1}.add-button.active[data-v-de93bb69]{background:linear-gradient(135deg,#f093fb 0,#f5576c);transform:translateY(-2px) scale(1.05) rotate(45deg);box-shadow:0 4px 16px #f5576c66}.add-button[data-v-de93bb69]:active{transform:translateY(0) scale(.98);transition:all .1s ease}.action-menu[data-v-de93bb69]{position:absolute;bottom:100%;left:0;margin-bottom:12px;background:#fffffffa;border:none;border-radius:16px;box-shadow:0 8px 32px #0000001f,0 2px 8px #00000014;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);overflow:hidden;z-index:1000;min-width:140px;transform:translateY(8px);opacity:0;animation:menuSlideIn-de93bb69 .3s cubic-bezier(.4,0,.2,1) forwards}.action-menu-item[data-v-de93bb69]{display:flex;align-items:center;gap:12px;padding:14px 18px;background:0 0;border:none;color:#333;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);width:100%;text-align:left;position:relative}.action-menu-item[data-v-de93bb69]:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:linear-gradient(135deg,#667eea 0,#764ba2);transform:scaleY(0);transition:transform .2s cubic-bezier(.4,0,.2,1)}.action-menu-item[data-v-de93bb69]:hover{background:linear-gradient(90deg,#667eea14 0,#764ba214);color:#667eea;transform:translate(4px)}.action-menu-item[data-v-de93bb69]:hover:before{transform:scaleY(1)}.action-menu-item svg[data-v-de93bb69]{flex-shrink:0}@media (prefers-color-scheme:dark){.action-menu[data-v-de93bb69]{background:#1e1e1efa;box-shadow:0 8px 32px #0000004d,0 2px 8px #0003}.action-menu-item[data-v-de93bb69]{color:#fff}.action-menu-item[data-v-de93bb69]:before{background:linear-gradient(135deg,#4facfe 0,#00f2fe)}.action-menu-item[data-v-de93bb69]:hover{background:linear-gradient(90deg,#4facfe1f 0,#00f2fe1f);color:#4facfe}.add-button[data-v-de93bb69]{background:linear-gradient(135deg,#4facfe 0,#00f2fe);box-shadow:0 2px 8px #4facfe4d}.add-button[data-v-de93bb69]:hover{box-shadow:0 4px 16px #4facfe66}.add-button.active[data-v-de93bb69]{background:linear-gradient(135deg,#fa709a 0,#fee140);box-shadow:0 4px 16px #fa709a66}.image-preview-item[data-v-de93bb69]{border-color:#64b5f680;background:#ffffff0d}}@media (max-width:768px){.image-preview-container[data-v-de93bb69]{padding:6px 0;margin-bottom:6px}.image-preview-item[data-v-de93bb69]{width:50px;height:50px}.add-button[data-v-de93bb69]{width:32px;height:32px;border-radius:10px}.action-menu[data-v-de93bb69]{min-width:100px}.action-menu-item[data-v-de93bb69]{padding:10px 12px;font-size:13px}.remove-image-btn[data-v-de93bb69]{width:18px;height:18px;top:-5px;right:-5px}}.message-history[data-v-de93bb69]::-webkit-scrollbar{width:6px}.message-history[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.message-history[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.message-history[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.bot-items[data-v-de93bb69]::-webkit-scrollbar{width:6px}.bot-items[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.bot-items[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.bot-items[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.channel-items[data-v-de93bb69]::-webkit-scrollbar{width:6px}.channel-items[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.channel-items[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.channel-items[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar{width:6px}.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.json-raw-content[data-v-de93bb69]::-webkit-scrollbar{width:6px}.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}@media (prefers-color-scheme:dark){.bot-items[data-v-de93bb69]::-webkit-scrollbar-thumb,.channel-items[data-v-de93bb69]::-webkit-scrollbar-thumb,.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-thumb,.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-thumb,.message-history[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#fff3}.bot-items[data-v-de93bb69]::-webkit-scrollbar-thumb:hover,.channel-items[data-v-de93bb69]::-webkit-scrollbar-thumb:hover,.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-thumb:hover,.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-thumb:hover,.message-history[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#fff6}}.layout-iframe{width:100%;height:100%;border:none}
1
+ .message-quote[data-v-de93bb69]{margin:8px 0;padding:8px 12px;background-color:#bebebe1a;border-left:4px solid rgba(151,152,152,.45);border-radius:6px;font-size:.9em;position:relative}.quote-indicator[data-v-de93bb69]{font-size:.75em;color:#007bff;font-weight:600;margin-bottom:4px;text-transform:uppercase}.quote-header[data-v-de93bb69]{display:flex;align-items:center;margin-bottom:4px;gap:6px}.quote-avatar[data-v-de93bb69]{width:20px;height:20px;border-radius:50%;overflow:hidden;flex-shrink:0}.quote-avatar img[data-v-de93bb69]{width:100%;height:100%;object-fit:cover}.quote-avatar .avatar-placeholder[data-v-de93bb69]{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background-color:#6c757d;color:#fff;font-size:10px;font-weight:700}.quote-username[data-v-de93bb69]{font-weight:600;color:#007bff;font-size:.85em}.quote-time[data-v-de93bb69]{color:#6c757d;font-size:.75em;margin-left:auto}.quote-content[data-v-de93bb69]{color:#7276b7;line-height:1.3;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto}.quote-content .message-image[data-v-de93bb69]{max-width:min(200px,50vw);max-height:100px}.quote-content .message-image-container[data-v-de93bb69]{margin:2px 0}@media (prefers-color-scheme:dark){.message-quote[data-v-de93bb69]{background-color:#ffffff14;border-left-color:#0d6efd}.quote-content[data-v-de93bb69]{color:#adb5bd}.quote-username[data-v-de93bb69]{color:#0d6efd}}.chat-container[data-v-de93bb69]{display:flex;height:100vh;background:0 0;margin-left:0;width:100%;overflow:hidden;color:inherit;position:relative}.bot-list[data-v-de93bb69],.channel-list[data-v-de93bb69],.message-area[data-v-de93bb69]{display:flex;flex-direction:column;background:0 0;border-right:1px solid rgba(128,128,128,.2)}.bot-list[data-v-de93bb69]{width:250px;min-width:250px;max-width:250px;flex-shrink:0}.channel-list[data-v-de93bb69]{width:300px;min-width:300px;max-width:300px;flex-shrink:0}.message-area[data-v-de93bb69]{flex:1;border-right:none}.panel-header[data-v-de93bb69]{padding:16px;border-bottom:1px solid rgba(128,128,128,.2);background:0 0;display:flex;align-items:center;justify-content:space-between}.panel-header h3[data-v-de93bb69]{margin:0;font-size:16px;font-weight:600;color:currentColor}.back-button[data-v-de93bb69]{display:none;background:0 0;border:none;color:currentColor;font-size:18px;cursor:pointer;padding:4px 8px;border-radius:4px;transition:background-color .2s}.back-button[data-v-de93bb69]:hover{background:#8080801a}.bot-items[data-v-de93bb69],.channel-items[data-v-de93bb69]{flex:1;overflow-y:auto;max-height:calc(100vh - 60px)}.bot-item[data-v-de93bb69],.channel-item[data-v-de93bb69]{display:flex;align-items:center;padding:12px 16px;cursor:pointer;border-bottom:1px solid rgba(128,128,128,.1);transition:background-color .2s}.bot-item[data-v-de93bb69]:hover,.channel-item[data-v-de93bb69]:hover{background:#8080801a}.bot-item.active[data-v-de93bb69],.channel-item.active[data-v-de93bb69]{background:#2196f31a;border-right:3px solid #2196f3}.bot-avatar[data-v-de93bb69]{width:40px;height:40px;margin-right:12px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;background:#e0e0e0}.bot-avatar img[data-v-de93bb69]{width:100%;height:100%;object-fit:cover}.avatar-placeholder[data-v-de93bb69]{font-size:16px;font-weight:700;color:currentColor;opacity:.7}.bot-info[data-v-de93bb69]{flex:1}.bot-name[data-v-de93bb69]{font-weight:500;color:currentColor;margin-bottom:2px}.bot-platform[data-v-de93bb69]{font-size:12px;color:currentColor;opacity:.7}.bot-status[data-v-de93bb69]{width:8px;height:8px;border-radius:50%;margin-left:8px}.bot-status.online[data-v-de93bb69]{background:#4caf50}.bot-status.offline[data-v-de93bb69]{background:#f44336}.channel-info[data-v-de93bb69]{flex:1}.channel-name[data-v-de93bb69]{font-weight:500;color:currentColor;margin-bottom:2px}.channel-type[data-v-de93bb69]{font-size:12px;color:currentColor;opacity:.7}.channel-message-count[data-v-de93bb69]{background:#2196f3;color:#fff;font-size:12px;padding:2px 6px;border-radius:10px;min-width:18px;text-align:center;position:relative;transition:all .2s ease}.channel-message-count.draggable-bubble[data-v-de93bb69]{cursor:grab;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.channel-message-count.draggable-bubble[data-v-de93bb69]:hover{background:#1976d2;transform:scale(1.1);box-shadow:0 2px 8px #2196f34d}.channel-message-count.draggable-bubble.dragging[data-v-de93bb69],.channel-message-count.draggable-bubble[data-v-de93bb69]:active{cursor:grabbing;background:#1565c0;box-shadow:0 4px 12px #2196f366}.dragging-clone[data-v-de93bb69]{position:fixed;z-index:1000;pointer-events:none;transition:none;box-sizing:border-box;display:flex;align-items:center;justify-content:center;background:#2196f3;color:#fff;font-size:12px;padding:2px 6px;border-radius:10px;min-width:18px;text-align:center;box-shadow:0 4px 12px #2196f366}.dragging-clone.will-delete[data-v-de93bb69]{background:#f44336!important;animation:shake-de93bb69 .3s ease-in-out infinite}@keyframes pulseThreshold-de93bb69{0%,to{opacity:.4;transform:scale(.9);border-color:#f4433699;box-shadow:0 0 15px #f4433633}50%{opacity:.8;transform:scale(1.1);border-color:#f44336;box-shadow:0 0 25px #f4433666}}@keyframes menuSlideIn-de93bb69{0%{transform:translateY(8px);opacity:0}to{transform:translateY(0);opacity:1}}.message-content[data-v-de93bb69]{display:flex;flex-direction:column;height:calc(100vh - 60px);overflow:hidden;position:relative}.message-history[data-v-de93bb69]{flex:1;overflow-y:auto;padding:16px 16px 8px;max-height:calc(100vh - 200px)}.message-item[data-v-de93bb69]{display:flex;margin-bottom:16px;padding:8px;border-radius:8px;transition:background-color .3s ease}.message-item[data-v-de93bb69]:hover{background-color:#8080801a}.message-item.new-message[data-v-de93bb69]{background-color:#4caf5033;animation:highlight-de93bb69 2s ease-out}.message-item.bot-message[data-v-de93bb69]{flex-direction:row-reverse;justify-content:flex-start}.message-item.bot-message .message-avatar[data-v-de93bb69]{margin-right:0;margin-left:12px}.message-item.bot-message .message-content-wrapper[data-v-de93bb69]{display:flex;flex-direction:column;align-items:flex-end}.message-item.bot-message .message-header[data-v-de93bb69]{display:flex;align-items:center;justify-content:flex-end;margin-bottom:4px}.message-item.bot-message .message-username[data-v-de93bb69]{margin-right:0;margin-left:8px;order:2}.message-item.bot-message .message-time[data-v-de93bb69]{order:1}.message-item.bot-message .message-text[data-v-de93bb69]{background-color:#2196f31a;padding:8px 12px;border-radius:12px 12px 4px;display:inline-block;max-width:80%;text-align:left;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere}@keyframes highlight-de93bb69{0%{background-color:#4caf504d}to{background-color:transparent}}.message-avatar[data-v-de93bb69]{width:32px;height:32px;margin-right:12px;border-radius:50%;overflow:hidden;display:flex;align-items:center;justify-content:center;background:#e0e0e0;flex-shrink:0}.message-avatar img[data-v-de93bb69]{width:100%;height:100%;object-fit:cover}.message-avatar .avatar-placeholder[data-v-de93bb69]{font-size:12px;font-weight:700;color:currentColor;opacity:.7}.message-content-wrapper[data-v-de93bb69]{flex:1}.message-header[data-v-de93bb69]{display:flex;align-items:center;margin-bottom:4px}.message-username[data-v-de93bb69]{font-weight:500;color:currentColor;margin-right:8px}.message-time[data-v-de93bb69]{font-size:12px;color:currentColor;opacity:.5}.message-text[data-v-de93bb69]{color:currentColor;line-height:1.4;word-wrap:break-word;word-break:break-all;white-space:pre-wrap;max-width:100%;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto}.message-item:not(.bot-message) .message-text[data-v-de93bb69]{background-color:#8080801a;padding:8px 12px;border-radius:12px 12px 12px 4px;display:inline-block;max-width:80%;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere}.message-input[data-v-de93bb69]{display:flex;flex-direction:column;padding:12px 16px 16px;border-top:1px solid rgba(128,128,128,.2);background:0 0;flex-shrink:0;position:sticky;bottom:0;margin-top:-10px}.input-row[data-v-de93bb69]{display:flex;gap:8px;align-items:center}.floating-scroll-button[data-v-de93bb69]{position:absolute;right:24px;bottom:18%;width:48px;height:48px;background:#2196f3;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 12px #2196f34d;color:#fff;transition:all .3s ease;z-index:100;border:2px solid rgba(255,255,255,.2)}.floating-scroll-button[data-v-de93bb69]:hover{background:#1976d2;transform:scale(1.1);box-shadow:0 6px 16px #2196f366}.floating-scroll-button[data-v-de93bb69]:active{transform:scale(.95)}.input-row button[data-v-de93bb69]{padding:8px 16px;background:#2196f3;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s}.message-image-container[data-v-de93bb69]{margin:8px 0;max-width:100%;display:block}.message-image[data-v-de93bb69]{border-radius:8px;object-fit:contain;display:block;cursor:pointer;transition:transform .2s ease;max-width:min(400px,66.67vw);max-height:200px;width:auto;height:auto;image-rendering:auto;-webkit-image-rendering:auto;-moz-image-rendering:auto;-o-image-rendering:auto}.message-image[src*=".gif"][data-v-de93bb69],.message-image[src*="image/gif"][data-v-de93bb69]{image-rendering:auto!important;-webkit-image-rendering:auto!important;animation-play-state:running!important}.message-image-loading[data-v-de93bb69]{display:inline-block;padding:8px 12px;background:#8080801a;border-radius:4px;color:currentColor;opacity:.7;font-size:12px}.message-image-error[data-v-de93bb69]{display:inline-block;padding:8px 12px;background:#f443361a;border:1px solid rgba(244,67,54,.3);border-radius:4px;color:#f44336;font-size:12px;max-width:300px;word-break:break-word}.message-paragraph[data-v-de93bb69]{display:block;margin-bottom:4px}.message-paragraph[data-v-de93bb69]:last-child{margin-bottom:0}.forward-message-container[data-v-de93bb69]{border:1px solid #fff;border-radius:8px;margin:4px 0;overflow:hidden;background:#f9f9f900}.forward-message-preview[data-v-de93bb69]{padding:12px;cursor:pointer;transition:background-color .2s}.forward-message-preview[data-v-de93bb69]:hover{background:#f0f0f0}.forward-message-title[data-v-de93bb69]{font-weight:600;color:#333;margin-bottom:8px;font-size:14px}.forward-message-preview-item[data-v-de93bb69]{color:#666;font-size:13px;margin:2px 0;line-height:1.4;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere}.forward-message-footer[data-v-de93bb69]{display:flex;justify-content:space-between;align-items:center;margin-top:8px;padding-top:8px;border-top:1px solid #e8e8e8}.forward-message-count[data-v-de93bb69]{color:#2196f3;font-size:12px}.forward-message-toggle[data-v-de93bb69]{color:#666;font-size:12px}.forward-message-expanded[data-v-de93bb69]{border-top:1px solid #e0e0e0;background:#fff;max-height:400px;overflow-y:auto}.forwarded-message-item[data-v-de93bb69]{padding:12px;border-bottom:1px solid #f0f0f0}.forwarded-message-item[data-v-de93bb69]:last-child{border-bottom:none}.forwarded-message-header[data-v-de93bb69]{display:flex;align-items:center;margin-bottom:6px}.forwarded-message-nickname[data-v-de93bb69]{font-weight:600;color:#333;font-size:13px}.forwarded-message-userid[data-v-de93bb69]{color:#999;font-size:11px;margin-left:6px}.forwarded-message-content[data-v-de93bb69]{color:#555;font-size:13px;line-height:1.4;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere}.message-at[data-v-de93bb69]{background:#2196f31a;color:#2196f3;padding:2px 4px;border-radius:3px;font-weight:500;cursor:pointer}.message-unknown[data-v-de93bb69]{background:#ff98001a;color:#ff9800;padding:2px 4px;border-radius:3px;font-style:italic;cursor:help}.input-row input[data-v-de93bb69]{flex:1;min-width:0;padding:8px 12px;border:1px solid rgba(128,128,128,.3);border-radius:4px;outline:0;background:0 0;color:currentColor}.input-row input[data-v-de93bb69]:focus{border-color:#2196f3;box-shadow:0 0 0 2px #2196f333}.input-row input[data-v-de93bb69]::placeholder{color:currentColor;opacity:.5}.input-row button[data-v-de93bb69]{padding:8px 16px;background:#2196f3;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;flex-shrink:0;white-space:nowrap}.input-row button[data-v-de93bb69]:hover:not(:disabled){background:#1976d2}.input-row button[data-v-de93bb69]:disabled{background:#8080804d;cursor:not-allowed}.input-row button.is-sending[data-v-de93bb69]{background:#ffc107!important;color:#333!important;cursor:default!important}.message-input .input-row button.is-sending[data-v-de93bb69]{background:#ffc107!important;color:#333!important;cursor:default!important;border-color:#ffc107!important}.empty-state[data-v-de93bb69]{display:flex;align-items:center;justify-content:center;height:100%;color:currentColor;opacity:.5;font-size:14px}.message-text-content[data-v-de93bb69]{display:inline;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto}.message-image-container[data-v-de93bb69]{display:block;margin:4px 0}.message-image[data-v-de93bb69]{border-radius:8px;margin:4px 0;display:block;cursor:pointer;transition:transform .2s ease;object-fit:contain;background:#8080801a}.message-image[data-v-de93bb69]:hover{transform:scale(1.02)}.message-image-loading[data-v-de93bb69]{height:60px;width:200px;border-radius:8px;margin:4px 0;display:flex;align-items:center;justify-content:center;background:#8080801a;color:currentColor;opacity:.7;font-size:14px;border:1px dashed rgba(128,128,128,.3)}.message-image-error[data-v-de93bb69]{min-height:60px;width:200px;border-radius:8px;margin:4px 0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#8080801a;color:currentColor;opacity:.7;font-size:14px;border:1px dashed rgba(128,128,128,.3);padding:8px;text-align:center}.message-at[data-v-de93bb69]{background:#2196f31a;color:#2196f3;padding:2px 6px;border-radius:4px;font-weight:500;cursor:pointer;display:inline-block;margin:0 2px}.message-at[data-v-de93bb69]:hover{background:#2196f333}.message-unknown[data-v-de93bb69]{background:#ff98001a;color:#ff9800;padding:2px 6px;border-radius:4px;font-size:12px;display:inline-block;margin:0 2px;cursor:help}@keyframes pulse-de93bb69{0%,to{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.1)}}.channel-message-count.will-delete[data-v-de93bb69]{background:#f44336!important;animation:shake-de93bb69 .3s ease-in-out infinite}@keyframes shake-de93bb69{0%,to{transform:translate(0)}25%{transform:translate(-2px)}75%{transform:translate(2px)}}body.dragging-bubble-global[data-v-de93bb69]{user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;cursor:grabbing}.drag-threshold-circle[data-v-de93bb69]{position:fixed;pointer-events:none;border:3px dashed rgba(244,67,54,.8);border-radius:50%;z-index:999;background:#f443361a;box-shadow:0 0 20px #f443364d;animation:pulseThreshold-de93bb69 1.5s ease-in-out infinite}.context-menu[data-v-de93bb69]{position:fixed;background:#ffffffa6;border:1px solid rgba(0,0,0,.1);border-radius:8px;box-shadow:0 8px 32px #00000026;z-index:10000;min-width:180px;backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);overflow:hidden}.context-menu-item[data-v-de93bb69]{padding:12px 16px;cursor:pointer;color:#333;font-size:14px;font-weight:500;transition:all .2s ease;border-bottom:1px solid rgba(0,0,0,.08);position:relative}.context-menu-item[data-v-de93bb69]:last-child{border-bottom:none}.context-menu-item[data-v-de93bb69]:hover{background:#2196f31a;color:#1976d2;transform:translate(2px)}.context-menu-item.danger[data-v-de93bb69]{color:#d32f2f}.context-menu-item.danger[data-v-de93bb69]:hover{background:#f443361a;color:#c62828}.bot-item.pinned[data-v-de93bb69],.channel-item.pinned[data-v-de93bb69]{background:#ffc1071a;border-left:3px solid #ffc107}.bot-item.pinned[data-v-de93bb69]:before,.channel-item.pinned[data-v-de93bb69]:before{content:"📌";position:absolute;left:4px;top:50%;transform:translateY(-50%);font-size:12px;opacity:.7}.bot-item.pinned[data-v-de93bb69],.channel-item.pinned[data-v-de93bb69]{position:relative;padding-left:24px}@media (prefers-color-scheme:dark){.context-menu[data-v-de93bb69]{background:#ffffff26;border-color:#fff3;box-shadow:0 8px 32px #0006}.context-menu-item[data-v-de93bb69]{color:#fff;border-bottom-color:#ffffff1a}.context-menu-item[data-v-de93bb69]:hover{background:#2196f333;color:#64b5f6}.context-menu-item.danger[data-v-de93bb69]{color:#ff8a80}.context-menu-item.danger[data-v-de93bb69]:hover{background:#f4433633;color:#ffab91}.bot-item.pinned[data-v-de93bb69],.channel-item.pinned[data-v-de93bb69]{background:#ffc10726}}.message-share-card[data-v-de93bb69]{display:inline-block;width:75px;margin:8px 0;border:1px solid rgba(128,128,128,.2);border-radius:12px;background:#ffffff0d;transition:all .3s ease;cursor:pointer;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.message-share-card[data-v-de93bb69]:hover{transform:translateY(-2px);box-shadow:0 8px 24px #00000026;border-color:#2196f34d}.share-card-preview[data-v-de93bb69]{width:100%;position:relative;display:flex;align-items:center;justify-content:center;padding:4px;border-radius:12px 12px 0 0}.share-card-image[data-v-de93bb69]{max-width:calc(100% - 8px);width:auto;height:auto;object-fit:contain;transition:transform .3s ease;display:block;border-radius:4px}.message-share-card:hover .share-card-image[data-v-de93bb69]{transform:scale(1.05)}.share-card-content[data-v-de93bb69]{padding:8px}.share-card-header[data-v-de93bb69]{display:flex;align-items:center;margin-bottom:12px;gap:12px}.share-card-icon[data-v-de93bb69]{width:32px;height:32px;border-radius:8px;object-fit:cover;flex-shrink:0}.share-card-app-info[data-v-de93bb69]{flex:1;min-width:0}.share-card-app-name[data-v-de93bb69]{font-size:12px;color:currentColor;opacity:.7;margin-bottom:2px;font-weight:500}.share-card-title[data-v-de93bb69]{font-size:10px;font-weight:600;color:currentColor;line-height:1.2;word-wrap:break-word;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden}.share-card-desc[data-v-de93bb69]{font-size:14px;color:currentColor;opacity:.8;line-height:1.4;margin-bottom:12px;display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;word-wrap:break-word}.share-card-link-hint[data-v-de93bb69]{font-size:12px;color:#2196f3;font-weight:500;display:flex;align-items:center;gap:4px}.share-card-link-hint[data-v-de93bb69]:after{content:"→";transition:transform .2s ease}.message-share-card:hover .share-card-link-hint[data-v-de93bb69]:after{transform:translate(2px)}.message-json-error[data-v-de93bb69],.message-json-raw[data-v-de93bb69]{display:inline-block;margin:8px 0;max-width:400px}.json-error-text[data-v-de93bb69]{color:#f44336;font-size:14px;font-weight:500}.json-label[data-v-de93bb69]{color:currentColor;opacity:.7;font-size:12px;font-weight:500;margin-bottom:8px}.json-raw-data[data-v-de93bb69]{margin-top:8px}.json-raw-data summary[data-v-de93bb69]{cursor:pointer;font-size:12px;color:#2196f3;font-weight:500;padding:4px 8px;border-radius:4px;background:#2196f31a;display:inline-block;transition:background-color .2s ease}.json-raw-data summary[data-v-de93bb69]:hover{background:#2196f333}.json-raw-content[data-v-de93bb69]{margin-top:8px;padding:12px;background:#8080801a;border-radius:8px;font-family:Courier New,monospace;font-size:12px;color:currentColor;opacity:.8;white-space:pre-wrap;word-wrap:break-word;word-break:break-all;overflow-wrap:anywhere;max-height:200px;overflow-y:auto;border:1px solid rgba(128,128,128,.2)}@media (prefers-color-scheme:dark){.message-share-card[data-v-de93bb69]{background:#ffffff14;border-color:#ffffff26}.message-share-card[data-v-de93bb69]:hover{border-color:#2196f380;box-shadow:0 8px 24px #0000004d}.json-raw-content[data-v-de93bb69]{background:#ffffff0d;border-color:#ffffff1a}}@media (max-width:768px){.chat-container[data-v-de93bb69]{position:relative;height:100vh;height:100dvh}.bot-list[data-v-de93bb69],.channel-list[data-v-de93bb69],.message-area[data-v-de93bb69]{position:absolute;top:0;left:0;width:100%;height:100%;transition:transform .3s ease;z-index:1}.bot-list[data-v-de93bb69]{transform:translate(0);z-index:3}.channel-list[data-v-de93bb69]{transform:translate(100%);z-index:2}.message-area[data-v-de93bb69]{transform:translate(200%);z-index:1}.chat-container.show-channels .bot-list[data-v-de93bb69]{transform:translate(-100%)}.chat-container.show-channels .channel-list[data-v-de93bb69]{transform:translate(0);z-index:3}.chat-container.show-channels .message-area[data-v-de93bb69]{transform:translate(100%)}.chat-container.show-messages .bot-list[data-v-de93bb69]{transform:translate(-200%)}.chat-container.show-messages .channel-list[data-v-de93bb69]{transform:translate(-100%)}.chat-container.show-messages .message-area[data-v-de93bb69]{transform:translate(0);z-index:3}.back-button[data-v-de93bb69]{display:none!important}.panel-header[data-v-de93bb69]{flex-direction:row-reverse;position:sticky;top:0;z-index:5;background:inherit}.panel-header h3[data-v-de93bb69]{text-align:right}.floating-scroll-button[data-v-de93bb69]{right:16px;bottom:calc(90px + env(safe-area-inset-bottom,0px));width:40px;height:40px;transition:bottom .3s ease}.message-input[data-v-de93bb69]{padding:8px 12px calc(12px + env(safe-area-inset-bottom,0px)) 12px;position:fixed;bottom:20px;left:0;right:0;background:inherit;border-top:1px solid rgba(128,128,128,.2);z-index:10;min-height:calc(60px + env(safe-area-inset-bottom,0px));transition:transform .3s ease;transform:translateZ(0)}.input-row input[data-v-de93bb69]{font-size:16px;padding:10px 12px}.input-row button[data-v-de93bb69]{padding:10px 16px;font-size:16px}.message-history[data-v-de93bb69]{padding:12px;max-height:calc(100vh - 140px - env(safe-area-inset-bottom,0px));max-height:calc(100dvh - 140px - env(safe-area-inset-bottom,0px));padding-bottom:calc(80px + env(safe-area-inset-bottom,0px));overflow-y:auto;-webkit-overflow-scrolling:touch;transition:max-height .3s ease}.message-item[data-v-de93bb69]{margin-bottom:12px;padding:6px}.message-text[data-v-de93bb69]{max-width:90%!important}.message-avatar[data-v-de93bb69]{width:28px;height:28px;margin-right:8px}.message-item.bot-message .message-avatar[data-v-de93bb69]{margin-left:8px}.message-image[data-v-de93bb69]{max-width:min(280px,66.67vw);max-height:160px}.quote-content .message-image[data-v-de93bb69]{max-width:min(150px,50vw);max-height:80px}.context-menu[data-v-de93bb69]{min-width:160px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}.context-menu-item[data-v-de93bb69]{padding:14px 16px;font-size:16px}.bot-item[data-v-de93bb69],.channel-item[data-v-de93bb69]{padding:14px 16px}.bot-avatar[data-v-de93bb69]{width:36px;height:36px;margin-right:10px}.bot-name[data-v-de93bb69],.channel-name[data-v-de93bb69]{font-size:15px}.bot-platform[data-v-de93bb69],.channel-type[data-v-de93bb69]{font-size:13px}}@media (min-width:769px) and (max-width:1024px){.bot-list[data-v-de93bb69]{width:220px;min-width:220px;max-width:220px}.channel-list[data-v-de93bb69]{width:280px;min-width:280px;max-width:280px}.message-image[data-v-de93bb69]{max-width:min(350px,66.67vw);max-height:180px}}.chat-container.swiping[data-v-de93bb69]{overflow:hidden}.bot-list.swiping[data-v-de93bb69],.channel-list.swiping[data-v-de93bb69],.message-area.swiping[data-v-de93bb69]{transition:none!important}.swipe-indicator[data-v-de93bb69]{position:fixed;top:50%;left:20px;transform:translateY(-50%);background:#2196f3cc;color:#fff;padding:8px 12px;border-radius:20px;font-size:14px;z-index:1000;opacity:0;transition:opacity .2s ease;pointer-events:none;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.swipe-indicator.show[data-v-de93bb69]{opacity:1}.message-area .message-content[data-v-de93bb69]{padding-bottom:80px}.image-preview-container[data-v-de93bb69]{display:flex;flex-wrap:wrap;gap:8px;padding:8px 0;margin-bottom:8px;border-bottom:1px solid rgba(128,128,128,.1)}.image-preview-item[data-v-de93bb69]{position:relative;width:60px;height:60px;border-radius:8px;overflow:hidden;border:2px solid rgba(33,150,243,.3);background:#8080801a}.preview-image[data-v-de93bb69]{width:100%;height:100%;object-fit:cover;display:block}.remove-image-btn[data-v-de93bb69]{position:absolute;top:-6px;right:-6px;width:20px;height:20px;border-radius:50%;background:#f44336;color:#fff;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:12px;transition:all .2s ease;box-shadow:0 2px 4px #0003}.remove-image-btn[data-v-de93bb69]:hover{background:#d32f2f;transform:scale(1.1)}.input-actions[data-v-de93bb69]{position:relative;margin-right:8px}.add-button[data-v-de93bb69]{width:36px;height:36px;border-radius:12px;background:linear-gradient(135deg,#667eea 0,#764ba2);border:none;color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .3s cubic-bezier(.4,0,.2,1);flex-shrink:0;box-shadow:0 2px 8px #667eea4d;position:relative;overflow:hidden}.add-button[data-v-de93bb69]:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(135deg,#fff3 0,#ffffff1a);border-radius:12px;opacity:0;transition:opacity .3s ease}.add-button[data-v-de93bb69]:hover{transform:translateY(-2px) scale(1.05);box-shadow:0 4px 16px #667eea66}.add-button[data-v-de93bb69]:hover:before{opacity:1}.add-button.active[data-v-de93bb69]{background:linear-gradient(135deg,#f093fb 0,#f5576c);transform:translateY(-2px) scale(1.05) rotate(45deg);box-shadow:0 4px 16px #f5576c66}.add-button[data-v-de93bb69]:active{transform:translateY(0) scale(.98);transition:all .1s ease}.action-menu[data-v-de93bb69]{position:absolute;bottom:100%;left:0;margin-bottom:12px;background:#fffffffa;border:none;border-radius:16px;box-shadow:0 8px 32px #0000001f,0 2px 8px #00000014;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);overflow:hidden;z-index:1000;min-width:140px;transform:translateY(8px);opacity:0;animation:menuSlideIn-de93bb69 .3s cubic-bezier(.4,0,.2,1) forwards}.action-menu-item[data-v-de93bb69]{display:flex;align-items:center;gap:12px;padding:14px 18px;background:0 0;border:none;color:#333;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);width:100%;text-align:left;position:relative}.action-menu-item[data-v-de93bb69]:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:linear-gradient(135deg,#667eea 0,#764ba2);transform:scaleY(0);transition:transform .2s cubic-bezier(.4,0,.2,1)}.action-menu-item[data-v-de93bb69]:hover{background:linear-gradient(90deg,#667eea14 0,#764ba214);color:#667eea;transform:translate(4px)}.action-menu-item[data-v-de93bb69]:hover:before{transform:scaleY(1)}.action-menu-item svg[data-v-de93bb69]{flex-shrink:0}@media (prefers-color-scheme:dark){.action-menu[data-v-de93bb69]{background:#1e1e1efa;box-shadow:0 8px 32px #0000004d,0 2px 8px #0003}.action-menu-item[data-v-de93bb69]{color:#fff}.action-menu-item[data-v-de93bb69]:before{background:linear-gradient(135deg,#4facfe 0,#00f2fe)}.action-menu-item[data-v-de93bb69]:hover{background:linear-gradient(90deg,#4facfe1f 0,#00f2fe1f);color:#4facfe}.add-button[data-v-de93bb69]{background:linear-gradient(135deg,#4facfe 0,#00f2fe);box-shadow:0 2px 8px #4facfe4d}.add-button[data-v-de93bb69]:hover{box-shadow:0 4px 16px #4facfe66}.add-button.active[data-v-de93bb69]{background:linear-gradient(135deg,#fa709a 0,#fee140);box-shadow:0 4px 16px #fa709a66}.image-preview-item[data-v-de93bb69]{border-color:#64b5f680;background:#ffffff0d}}@media (max-width:768px){.image-preview-container[data-v-de93bb69]{padding:6px 0;margin-bottom:6px}.image-preview-item[data-v-de93bb69]{width:50px;height:50px}.add-button[data-v-de93bb69]{width:32px;height:32px;border-radius:10px}.action-menu[data-v-de93bb69]{min-width:100px}.action-menu-item[data-v-de93bb69]{padding:10px 12px;font-size:13px}.remove-image-btn[data-v-de93bb69]{width:18px;height:18px;top:-5px;right:-5px}}.message-history[data-v-de93bb69]::-webkit-scrollbar{width:6px}.message-history[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.message-history[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.message-history[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.bot-items[data-v-de93bb69]::-webkit-scrollbar{width:6px}.bot-items[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.bot-items[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.bot-items[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.channel-items[data-v-de93bb69]::-webkit-scrollbar{width:6px}.channel-items[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.channel-items[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.channel-items[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar{width:6px}.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.json-raw-content[data-v-de93bb69]::-webkit-scrollbar{width:6px}.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-track{background:0 0}.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#90939980}@media (prefers-color-scheme:dark){.bot-items[data-v-de93bb69]::-webkit-scrollbar-thumb,.channel-items[data-v-de93bb69]::-webkit-scrollbar-thumb,.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-thumb,.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-thumb,.message-history[data-v-de93bb69]::-webkit-scrollbar-thumb{background-color:#fff3}.bot-items[data-v-de93bb69]::-webkit-scrollbar-thumb:hover,.channel-items[data-v-de93bb69]::-webkit-scrollbar-thumb:hover,.forward-message-expanded[data-v-de93bb69]::-webkit-scrollbar-thumb:hover,.json-raw-content[data-v-de93bb69]::-webkit-scrollbar-thumb:hover,.message-history[data-v-de93bb69]::-webkit-scrollbar-thumb:hover{background-color:#fff6}}.layout-iframe{width:100%;height:100%;border:none}
package/lib/index.js CHANGED
@@ -138,6 +138,17 @@ var MessageHandler = class {
138
138
  }
139
139
  logger;
140
140
  utils;
141
+ // 存储正确的 channelId 映射,key 是 selfId,value 是正确的 channelId
142
+ correctChannelIds = /* @__PURE__ */ new Map();
143
+ // 设置正确的 channelId
144
+ setCorrectChannelId(selfId, channelId) {
145
+ this.correctChannelIds.set(selfId, channelId);
146
+ this.logInfo("设置正确的 channelId:", { selfId, channelId });
147
+ }
148
+ // 获取正确的 channelId
149
+ getCorrectChannelId(selfId) {
150
+ return this.correctChannelIds.get(selfId);
151
+ }
141
152
  // 更新机器人信息到JSON文件
142
153
  async updateBotInfoToFile(session) {
143
154
  const data = this.fileManager.readChatDataFromFile();
@@ -170,10 +181,11 @@ var MessageHandler = class {
170
181
  }
171
182
  const channelInfo = {
172
183
  id: session.channelId,
173
- name: session.guildId ? `${guildName} (${session.channelId})` : `私信 ${session.channelId}`,
184
+ name: session.isDirect ? `私信 ${session.channelId}` : `${guildName} (${session.channelId})`,
174
185
  type: session.type || 0,
175
- guildId: session.guildId,
176
- guildName
186
+ channelId: session.channelId,
187
+ guildName,
188
+ isDirect: session.isDirect
177
189
  };
178
190
  data.channels[session.selfId][session.channelId] = channelInfo;
179
191
  this.fileManager.writeChatDataToFile(data);
@@ -226,10 +238,10 @@ var MessageHandler = class {
226
238
  selfId: session.selfId,
227
239
  elements: this.utils.cleanBase64Content(elements),
228
240
  type: "user",
229
- guildId: session.guildId,
230
241
  guildName,
231
242
  platform: session.platform || "unknown",
232
- quote: quoteInfo ? this.utils.cleanBase64Content(quoteInfo) : void 0
243
+ quote: quoteInfo ? this.utils.cleanBase64Content(quoteInfo) : void 0,
244
+ isDirect: session.isDirect
233
245
  };
234
246
  await this.fileManager.addMessageToFile(messageInfo);
235
247
  const messageEvent = {
@@ -243,11 +255,11 @@ var MessageHandler = class {
243
255
  username: session.username || session.event?.user?.name || session.userId || "unknown",
244
256
  avatar: session.event?.user?.avatar,
245
257
  timestamp,
246
- guildId: session.guildId,
247
258
  guildName,
248
259
  channelType: session.type || 0,
249
260
  elements: this.utils.cleanBase64Content(elements),
250
261
  quote: quoteInfo ? this.utils.cleanBase64Content(quoteInfo) : void 0,
262
+ isDirect: session.isDirect,
251
263
  bot: {
252
264
  avatar: session.bot.user?.avatar,
253
265
  name: session.bot.user?.name
@@ -261,6 +273,16 @@ var MessageHandler = class {
261
273
  // 处理机器人发送的消息
262
274
  async broadcastBotMessageEvent(session) {
263
275
  try {
276
+ const correctChannelId = this.getCorrectChannelId(session.selfId);
277
+ this.logInfo("机器人发送消息调试信息:", {
278
+ "session.channelId": session.channelId,
279
+ "session.event?.channel?.id": session.event?.channel?.id,
280
+ "correctChannelId": correctChannelId,
281
+ "session.guildId": session.guildId,
282
+ "session.isDirect": session.isDirect,
283
+ "session.platform": session.platform
284
+ });
285
+ const finalChannelId = correctChannelId || session.channelId;
264
286
  await this.updateBotInfoToFile(session);
265
287
  const guildName = await this.updateChannelInfoToFile(session);
266
288
  const timestamp = Date.now();
@@ -275,30 +297,30 @@ var MessageHandler = class {
275
297
  username: session.bot.user?.name || `Bot-${session.selfId}`,
276
298
  avatar: session.bot.user?.avatar,
277
299
  timestamp,
278
- channelId: session.event?.channel?.id || session.channelId,
300
+ channelId: finalChannelId,
279
301
  selfId: session.selfId,
280
302
  elements: this.utils.cleanBase64Content(session.event?.message?.elements),
281
303
  type: "bot",
282
- guildId: session.event?.guild?.id || session.guildId,
283
304
  guildName,
284
- platform: session.platform || "unknown"
305
+ platform: session.platform || "unknown",
306
+ isDirect: session.isDirect
285
307
  };
286
308
  await this.fileManager.addMessageToFile(messageInfo);
287
309
  const messageEvent = {
288
310
  type: "bot-message",
289
311
  selfId: session.selfId,
290
312
  platform: session.platform || "unknown",
291
- channelId: session.event?.channel?.id || session.channelId,
313
+ channelId: finalChannelId,
292
314
  messageId: `bot-msg-${timestamp}`,
293
315
  content,
294
316
  userId: session.selfId,
295
317
  username: session.bot.user?.name || `Bot-${session.selfId}`,
296
318
  avatar: session.bot.user?.avatar,
297
319
  timestamp,
298
- guildId: session.event?.guild?.id || session.guildId,
299
320
  guildName,
300
321
  channelType: session.event?.channel?.type || session.type || 0,
301
322
  elements: this.utils.cleanBase64Content(session.event?.message?.elements),
323
+ isDirect: session.isDirect,
302
324
  bot: {
303
325
  avatar: session.bot.user?.avatar,
304
326
  name: session.bot.user?.name
@@ -310,11 +332,14 @@ var MessageHandler = class {
310
332
  this.logInfo("机器人发送消息 (before-send):", {
311
333
  selfId: session.selfId,
312
334
  channelId: messageEvent.channelId,
335
+ originalChannelId: session.channelId,
336
+ correctedChannelId: finalChannelId,
313
337
  content,
314
338
  platform: session.platform,
315
339
  imageCount: imageElements.length,
316
340
  imageUrls: imageElements.map((el) => el.attrs?.src || el.attrs?.url || el.attrs?.file)
317
341
  });
342
+ this.correctChannelIds.delete(session.selfId);
318
343
  this.ctx.console.broadcast("chat-bot-message-event", messageEvent);
319
344
  } catch (error) {
320
345
  this.logger.error("广播机器人消息事件失败:", error);
@@ -474,10 +499,11 @@ var FileManager = class {
474
499
  var import_koishi = require("koishi");
475
500
  var import_node_url = require("node:url");
476
501
  var ApiHandlers = class {
477
- constructor(ctx, config, fileManager) {
502
+ constructor(ctx, config, fileManager, messageHandler) {
478
503
  this.ctx = ctx;
479
504
  this.config = config;
480
505
  this.fileManager = fileManager;
506
+ this.messageHandler = messageHandler;
481
507
  this.logger = ctx.logger("chat-patch");
482
508
  }
483
509
  static {
@@ -630,6 +656,7 @@ var ApiHandlers = class {
630
656
  }
631
657
  }
632
658
  }
659
+ this.messageHandler.setCorrectChannelId(data.selfId, data.channelId);
633
660
  const result = await bot.sendMessage(data.channelId, messageContent);
634
661
  this.logInfo("消息发送成功:", result);
635
662
  return {
@@ -737,11 +764,11 @@ var ApiHandlers = class {
737
764
  });
738
765
  this.ctx.console.addListener("upload-image", async (data) => {
739
766
  try {
740
- this.logInfo("收到图片上传请求:", { filename: data.filename, mimeType: data.mimeType });
767
+ this.logInfo("收到图片上传请求:", { filename: data.filename, mimeType: data.mimeType, isGif: data.isGif });
741
768
  const base64Data = data.file.replace(/^data:image\/\w+;base64,/, "");
742
769
  const buffer = Buffer.from(base64Data, "base64");
743
770
  const tempId = Date.now() + "_" + Math.random().toString(36).substring(2, 11);
744
- const extension = data.filename.split(".").pop() || "jpg";
771
+ const extension = data.filename.split(".").pop()?.toLowerCase() || (data.isGif ? "gif" : "jpg");
745
772
  const tempFilename = `temp_${tempId}.${extension}`;
746
773
  const tempDir = this.ctx.baseDir + "/data/chat-patch/temp";
747
774
  if (!require("fs").existsSync(tempDir)) {
@@ -749,13 +776,14 @@ var ApiHandlers = class {
749
776
  }
750
777
  const tempPath = `${tempDir}/${tempFilename}`;
751
778
  require("fs").writeFileSync(tempPath, buffer);
752
- this.logInfo("图片上传成功:", { tempPath, size: buffer.length });
779
+ this.logInfo("图片上传成功:", { tempPath, size: buffer.length, isGif: data.isGif });
753
780
  return {
754
781
  success: true,
755
782
  tempId,
756
783
  tempPath,
757
784
  filename: data.filename,
758
- size: buffer.length
785
+ size: buffer.length,
786
+ isGif: data.isGif
759
787
  };
760
788
  } catch (error) {
761
789
  this.logger.error("图片上传失败:", error);
@@ -972,7 +1000,7 @@ async function apply(ctx, config) {
972
1000
  const logger = ctx.logger("chat-patch");
973
1001
  const fileManager = new FileManager(ctx, config);
974
1002
  const messageHandler = new MessageHandler(ctx, config, fileManager);
975
- const apiHandlers = new ApiHandlers(ctx, config, fileManager);
1003
+ const apiHandlers = new ApiHandlers(ctx, config, fileManager, messageHandler);
976
1004
  const utils = new Utils(config);
977
1005
  const initialData = fileManager.readChatDataFromFile();
978
1006
  const cleanedData = fileManager.cleanExcessMessages(initialData);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chat-patch",
3
3
  "description": "[<ruby>chat-patch<rp>(</rp><rt>点我预览效果</rt><rp>)</rp></ruby>](https://i0.hdslb.com/bfs/openplatform/71074dfc9e5256fc3333d8bd8478bec1af874046.png) 视奸小插件((bushi( (低性能警告)。手机端适配。灵感来自 chat 插件。",
4
- "version": "1.0.14",
4
+ "version": "1.0.16",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -1,4 +1,5 @@
1
1
  import { FileManager } from './file-manager'
2
+ import { MessageHandler } from './message-handler'
2
3
  import { Context, h, Logger } from 'koishi'
3
4
  import { Config } from './config'
4
5
 
@@ -10,7 +11,8 @@ export class ApiHandlers {
10
11
  constructor(
11
12
  private ctx: Context,
12
13
  private config: Config,
13
- private fileManager: FileManager
14
+ private fileManager: FileManager,
15
+ private messageHandler: MessageHandler
14
16
  ) {
15
17
  this.logger = ctx.logger('chat-patch')
16
18
  }
@@ -218,6 +220,9 @@ export class ApiHandlers {
218
220
  }
219
221
  }
220
222
 
223
+ // 在发送消息前,通知 MessageHandler 正确的 channelId
224
+ this.messageHandler.setCorrectChannelId(data.selfId, data.channelId)
225
+
221
226
  const result = await bot.sendMessage(data.channelId, messageContent)
222
227
  this.logInfo('消息发送成功:', result)
223
228
 
@@ -366,17 +371,18 @@ export class ApiHandlers {
366
371
  file: string // base64 encoded image
367
372
  filename: string
368
373
  mimeType: string
374
+ isGif?: boolean // 是否为GIF图片
369
375
  }) => {
370
376
  try {
371
- this.logInfo('收到图片上传请求:', { filename: data.filename, mimeType: data.mimeType })
377
+ this.logInfo('收到图片上传请求:', { filename: data.filename, mimeType: data.mimeType, isGif: data.isGif })
372
378
 
373
379
  // 将base64转换为Buffer
374
380
  const base64Data = data.file.replace(/^data:image\/\w+;base64,/, '')
375
381
  const buffer = Buffer.from(base64Data, 'base64')
376
382
 
377
- // 生成临时文件路径
383
+ // 生成临时文件路径,保持原始扩展名以保持GIF格式
378
384
  const tempId = Date.now() + '_' + Math.random().toString(36).substring(2, 11)
379
- const extension = data.filename.split('.').pop() || 'jpg'
385
+ const extension = data.filename.split('.').pop()?.toLowerCase() || (data.isGif ? 'gif' : 'jpg')
380
386
  const tempFilename = `temp_${tempId}.${extension}`
381
387
 
382
388
  // 保存到临时目录
@@ -386,16 +392,19 @@ export class ApiHandlers {
386
392
  }
387
393
 
388
394
  const tempPath = `${tempDir}/${tempFilename}`
395
+
396
+ // 对于GIF文件,直接保存原始数据以保持动画
389
397
  require('fs').writeFileSync(tempPath, buffer)
390
398
 
391
- this.logInfo('图片上传成功:', { tempPath, size: buffer.length })
399
+ this.logInfo('图片上传成功:', { tempPath, size: buffer.length, isGif: data.isGif })
392
400
 
393
401
  return {
394
402
  success: true,
395
403
  tempId: tempId,
396
404
  tempPath: tempPath,
397
405
  filename: data.filename,
398
- size: buffer.length
406
+ size: buffer.length,
407
+ isGif: data.isGif
399
408
  }
400
409
  } catch (error: any) {
401
410
  this.logger.error('图片上传失败:', error)
package/src/index.ts CHANGED
@@ -35,7 +35,7 @@ export async function apply(ctx: Context, config: Config) {
35
35
  // 初始化各个模块
36
36
  const fileManager = new FileManager(ctx, config)
37
37
  const messageHandler = new MessageHandler(ctx, config, fileManager)
38
- const apiHandlers = new ApiHandlers(ctx, config, fileManager)
38
+ const apiHandlers = new ApiHandlers(ctx, config, fileManager, messageHandler)
39
39
  const utils = new Utils(config)
40
40
 
41
41
  // 初始化数据
@@ -7,6 +7,8 @@ import { Utils } from './utils'
7
7
  export class MessageHandler {
8
8
  private logger: Logger
9
9
  private utils: Utils
10
+ // 存储正确的 channelId 映射,key 是 selfId,value 是正确的 channelId
11
+ private correctChannelIds: Map<string, string> = new Map()
10
12
 
11
13
  constructor(
12
14
  private ctx: Context,
@@ -17,6 +19,17 @@ export class MessageHandler {
17
19
  this.utils = new Utils(config)
18
20
  }
19
21
 
22
+ // 设置正确的 channelId
23
+ setCorrectChannelId(selfId: string, channelId: string) {
24
+ this.correctChannelIds.set(selfId, channelId)
25
+ this.logInfo('设置正确的 channelId:', { selfId, channelId })
26
+ }
27
+
28
+ // 获取正确的 channelId
29
+ getCorrectChannelId(selfId: string): string | undefined {
30
+ return this.correctChannelIds.get(selfId)
31
+ }
32
+
20
33
  // 更新机器人信息到JSON文件
21
34
  async updateBotInfoToFile(session: Session) {
22
35
  const data = this.fileManager.readChatDataFromFile()
@@ -56,12 +69,13 @@ export class MessageHandler {
56
69
 
57
70
  const channelInfo: ChannelInfo = {
58
71
  id: session.channelId,
59
- name: session.guildId
60
- ? `${guildName} (${session.channelId})`
61
- : `私信 ${session.channelId}`,
72
+ name: session.isDirect
73
+ ? `私信 ${session.channelId}`
74
+ : `${guildName} (${session.channelId})`,
62
75
  type: session.type || 0,
63
- guildId: session.guildId,
64
- guildName: guildName
76
+ channelId: session.channelId,
77
+ guildName: guildName,
78
+ isDirect: session.isDirect
65
79
  }
66
80
 
67
81
  data.channels[session.selfId][session.channelId] = channelInfo
@@ -129,10 +143,10 @@ export class MessageHandler {
129
143
  selfId: session.selfId,
130
144
  elements: this.utils.cleanBase64Content(elements),
131
145
  type: 'user',
132
- guildId: session.guildId,
133
146
  guildName: guildName,
134
147
  platform: session.platform || 'unknown',
135
- quote: quoteInfo ? this.utils.cleanBase64Content(quoteInfo) : undefined
148
+ quote: quoteInfo ? this.utils.cleanBase64Content(quoteInfo) : undefined,
149
+ isDirect: session.isDirect
136
150
  }
137
151
 
138
152
  await this.fileManager.addMessageToFile(messageInfo)
@@ -148,11 +162,11 @@ export class MessageHandler {
148
162
  username: session.username || session.event?.user?.name || session.userId || 'unknown',
149
163
  avatar: session.event?.user?.avatar,
150
164
  timestamp: timestamp,
151
- guildId: session.guildId,
152
165
  guildName: guildName,
153
166
  channelType: session.type || 0,
154
167
  elements: this.utils.cleanBase64Content(elements),
155
168
  quote: quoteInfo ? this.utils.cleanBase64Content(quoteInfo) : undefined,
169
+ isDirect: session.isDirect,
156
170
  bot: {
157
171
  avatar: session.bot.user?.avatar,
158
172
  name: session.bot.user?.name,
@@ -168,6 +182,22 @@ export class MessageHandler {
168
182
  // 处理机器人发送的消息
169
183
  async broadcastBotMessageEvent(session: Session) {
170
184
  try {
185
+ // 获取正确的 channelId
186
+ const correctChannelId = this.getCorrectChannelId(session.selfId)
187
+
188
+ // 调试日志:检查 channelId 的来源
189
+ this.logInfo('机器人发送消息调试信息:', {
190
+ 'session.channelId': session.channelId,
191
+ 'session.event?.channel?.id': session.event?.channel?.id,
192
+ 'correctChannelId': correctChannelId,
193
+ 'session.guildId': session.guildId,
194
+ 'session.isDirect': session.isDirect,
195
+ 'session.platform': session.platform
196
+ })
197
+
198
+ // 使用正确的 channelId,如果没有则使用 session.channelId
199
+ const finalChannelId = correctChannelId || session.channelId
200
+
171
201
  await this.updateBotInfoToFile(session)
172
202
  const guildName = await this.updateChannelInfoToFile(session)
173
203
 
@@ -187,13 +217,13 @@ export class MessageHandler {
187
217
  username: session.bot.user?.name || `Bot-${session.selfId}`,
188
218
  avatar: session.bot.user?.avatar,
189
219
  timestamp: timestamp,
190
- channelId: session.event?.channel?.id || session.channelId,
220
+ channelId: finalChannelId,
191
221
  selfId: session.selfId,
192
222
  elements: this.utils.cleanBase64Content(session.event?.message?.elements),
193
223
  type: 'bot',
194
- guildId: session.event?.guild?.id || session.guildId,
195
224
  guildName: guildName,
196
- platform: session.platform || 'unknown'
225
+ platform: session.platform || 'unknown',
226
+ isDirect: session.isDirect
197
227
  }
198
228
 
199
229
  await this.fileManager.addMessageToFile(messageInfo)
@@ -202,17 +232,17 @@ export class MessageHandler {
202
232
  type: 'bot-message',
203
233
  selfId: session.selfId,
204
234
  platform: session.platform || 'unknown',
205
- channelId: session.event?.channel?.id || session.channelId,
235
+ channelId: finalChannelId,
206
236
  messageId: `bot-msg-${timestamp}`,
207
237
  content: content,
208
238
  userId: session.selfId,
209
239
  username: session.bot.user?.name || `Bot-${session.selfId}`,
210
240
  avatar: session.bot.user?.avatar,
211
241
  timestamp: timestamp,
212
- guildId: session.event?.guild?.id || session.guildId,
213
242
  guildName: guildName,
214
243
  channelType: session.event?.channel?.type || session.type || 0,
215
244
  elements: this.utils.cleanBase64Content(session.event?.message?.elements),
245
+ isDirect: session.isDirect,
216
246
  bot: {
217
247
  avatar: session.bot.user?.avatar,
218
248
  name: session.bot.user?.name,
@@ -227,12 +257,17 @@ export class MessageHandler {
227
257
  this.logInfo('机器人发送消息 (before-send):', {
228
258
  selfId: session.selfId,
229
259
  channelId: messageEvent.channelId,
260
+ originalChannelId: session.channelId,
261
+ correctedChannelId: finalChannelId,
230
262
  content: content,
231
263
  platform: session.platform,
232
264
  imageCount: imageElements.length,
233
265
  imageUrls: imageElements.map((el: any) => el.attrs?.src || el.attrs?.url || el.attrs?.file)
234
266
  })
235
267
 
268
+ // 清理已使用的 channelId 映射
269
+ this.correctChannelIds.delete(session.selfId)
270
+
236
271
  this.ctx.console.broadcast('chat-bot-message-event', messageEvent)
237
272
  } catch (error) {
238
273
  this.logger.error('广播机器人消息事件失败:', error)
package/src/types.ts CHANGED
@@ -12,8 +12,9 @@ export interface ChannelInfo {
12
12
  id: string
13
13
  name: string
14
14
  type: number | string
15
- guildId?: string
15
+ channelId?: string
16
16
  guildName?: string
17
+ isDirect?: boolean
17
18
  }
18
19
 
19
20
  export interface QuoteInfo {
@@ -46,6 +47,7 @@ export interface MessageInfo {
46
47
  guildName?: string
47
48
  platform: string
48
49
  quote?: QuoteInfo
50
+ isDirect?: boolean
49
51
  }
50
52
 
51
53
  export interface ChatData {