koishi-plugin-chat-patch 1.0.8 → 1.0.10

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.
@@ -222,7 +222,6 @@ function isFileUrl(url: string): boolean {
222
222
  }
223
223
  }
224
224
 
225
-
226
225
  // 头像组件
227
226
  const AvatarComponent = defineComponent({
228
227
  props: {
@@ -699,16 +698,6 @@ const MessageElement = defineComponent({
699
698
  case 'img':
700
699
  case 'image':
701
700
  const imageUrl = element.attrs.src || element.attrs.url || element.attrs.file
702
-
703
- // 调试信息:记录图片 URL 类型
704
- if (imageUrl && isFileUrl(imageUrl)) {
705
- console.log('检测到本地文件路径:', imageUrl)
706
- } else if (imageUrl?.startsWith('http')) {
707
- console.log('检测到网络图片:', imageUrl)
708
- } else {
709
- console.log('检测到其他类型图片URL:', imageUrl)
710
- }
711
-
712
701
  return h('div', { class: 'message-image-container' }, [
713
702
  h(ImageComponent, {
714
703
  src: imageUrl,
@@ -720,12 +709,6 @@ const MessageElement = defineComponent({
720
709
 
721
710
  case 'mface':
722
711
  const mfaceimageUrl = element.attrs.src || element.attrs.url || element.attrs.file
723
-
724
- // 调试信息:记录表情图片 URL 类型
725
- if (mfaceimageUrl && isFileUrl(mfaceimageUrl)) {
726
- console.log('检测到本地表情文件路径:', mfaceimageUrl)
727
- }
728
-
729
712
  return h('div', { class: 'message-image-container' }, [
730
713
  h(ImageComponent, {
731
714
  src: mfaceimageUrl,
@@ -899,13 +882,35 @@ interface ImageCacheItem {
899
882
 
900
883
  // 内存中的URL缓存
901
884
  const imageBlobUrls = ref<Record<string, string>>({})
902
- const maxImagesPerChannel = 200 // 每个频道最大缓存图片数量
903
885
 
904
886
  // 内存管理配置
905
887
  const MAX_MEMORY_USAGE = 100 * 1024 * 1024 // 100MB 最大内存使用量
906
888
  const MAX_BLOB_COUNT = 50 // 最大blob URL数量
907
889
  let currentMemoryUsage = 0 // 当前内存使用量估算
908
890
 
891
+ // IndexedDB 配置和限制
892
+ let imageDB: IDBDatabase | null = null
893
+ const DB_NAME = 'ChatImageCache'
894
+ const DB_VERSION = 2 // 版本号
895
+ const STORE_NAME = 'images'
896
+
897
+ // 严格的存储限制
898
+ const MAX_DB_SIZE = 50 * 1024 * 1024 // 50MB 最大数据库大小
899
+ const MAX_IMAGES_PER_CHANNEL = 100 // 每个频道最多缓存100张图片
900
+ const MAX_TOTAL_IMAGES = 500 // 总共最多缓存500张图片
901
+ const MAX_IMAGE_SIZE = 2 * 1024 * 1024 // 单张图片最大2MB
902
+ const CLEANUP_THRESHOLD = 0.8 // 当达到80%限制时开始清理
903
+ const DB_HEALTH_CHECK_INTERVAL = 60 * 1000 // 每分钟检查一次数据库健康状态
904
+
905
+ // 数据库状态跟踪
906
+ let currentDbSize = 0
907
+ let currentImageCount = 0
908
+ let lastHealthCheck = 0
909
+
910
+ const selectedBot = ref<string>('')
911
+ const selectedChannel = ref<string>('')
912
+ const inputMessage = ref<string>('')
913
+
909
914
  // 内存管理函数
910
915
  function estimateBlobSize(blob: Blob): number {
911
916
  return blob.size || 0
@@ -954,16 +959,6 @@ function checkAndCleanupMemory() {
954
959
  }
955
960
  }
956
961
 
957
- // IndexedDB
958
- let imageDB: IDBDatabase | null = null
959
- const DB_NAME = 'ChatImageCache'
960
- const DB_VERSION = 1
961
- const STORE_NAME = 'images'
962
-
963
- const selectedBot = ref<string>('')
964
- const selectedChannel = ref<string>('')
965
- const inputMessage = ref<string>('')
966
-
967
962
  // 图片上传相关状态
968
963
  const uploadedImages = ref<Array<{
969
964
  tempId: string
@@ -971,6 +966,7 @@ const uploadedImages = ref<Array<{
971
966
  preview: string
972
967
  size: number
973
968
  }>>([])
969
+
974
970
  const showActionMenu = ref<boolean>(false)
975
971
  const fileInput = ref<HTMLInputElement>()
976
972
 
@@ -1771,7 +1767,6 @@ function resetDragState() {
1771
1767
  removeThresholdCircle()
1772
1768
  }
1773
1769
 
1774
- // getDragStyle 不再直接用于拖拽中的元素,而是用于原始元素隐藏
1775
1770
  function getDragStyle(channelId: string) {
1776
1771
  if (draggingChannel.value === channelId && isDragReady.value) {
1777
1772
  // 当拖拽开始且准备就绪时,隐藏原始气泡
@@ -1951,30 +1946,319 @@ function removeThresholdCircle() {
1951
1946
  }
1952
1947
  }
1953
1948
 
1954
- // IndexedDB初始化
1955
- async function initImageDB(): Promise<boolean> {
1956
- return new Promise((resolve, reject) => {
1957
- const request = indexedDB.open(DB_NAME, DB_VERSION)
1949
+ // 数据库健康检查
1950
+ async function checkDatabaseHealth(): Promise<boolean> {
1951
+ try {
1952
+ if (!imageDB) return false
1953
+
1954
+ const now = Date.now()
1955
+ if (now - lastHealthCheck < DB_HEALTH_CHECK_INTERVAL) {
1956
+ return true // 跳过频繁检查
1957
+ }
1958
+
1959
+ lastHealthCheck = now
1960
+
1961
+ // 获取数据库统计信息
1962
+ const stats = await getDatabaseStats()
1963
+ currentDbSize = stats.totalSize
1964
+ currentImageCount = stats.totalImages
1965
+
1966
+ console.log('数据库健康检查:', {
1967
+ 大小: `${(currentDbSize / 1024 / 1024).toFixed(2)}MB / ${(MAX_DB_SIZE / 1024 / 1024).toFixed(2)}MB`,
1968
+ 图片数量: `${currentImageCount} / ${MAX_TOTAL_IMAGES}`,
1969
+ 使用率: `${(currentDbSize / MAX_DB_SIZE * 100).toFixed(1)}%`
1970
+ })
1971
+
1972
+ // 检查是否需要清理
1973
+ const sizeRatio = currentDbSize / MAX_DB_SIZE
1974
+ const countRatio = currentImageCount / MAX_TOTAL_IMAGES
1975
+
1976
+ if (sizeRatio > CLEANUP_THRESHOLD || countRatio > CLEANUP_THRESHOLD) {
1977
+ console.warn('数据库使用率过高,开始自动清理')
1978
+ await performAutomaticCleanup()
1979
+ }
1980
+
1981
+ // 检查是否超过硬限制
1982
+ if (sizeRatio > 0.95 || countRatio > 0.95) {
1983
+ console.error('数据库接近极限,执行紧急清理')
1984
+ await performEmergencyCleanup()
1985
+ }
1986
+
1987
+ return true
1988
+ } catch (error) {
1989
+ console.error('数据库健康检查失败:', error)
1990
+ return false
1991
+ }
1992
+ }
1993
+
1994
+ // 获取数据库统计信息
1995
+ async function getDatabaseStats(): Promise<{ totalSize: number, totalImages: number, channelStats: Record<string, number> }> {
1996
+ if (!imageDB) return { totalSize: 0, totalImages: 0, channelStats: {} }
1997
+
1998
+ return new Promise((resolve) => {
1999
+ const transaction = imageDB!.transaction([STORE_NAME], 'readonly')
2000
+ const store = transaction.objectStore(STORE_NAME)
2001
+ const request = store.getAll()
2002
+
2003
+ request.onsuccess = () => {
2004
+ const items: ImageCacheItem[] = request.result || []
2005
+ let totalSize = 0
2006
+ const channelStats: Record<string, number> = {}
2007
+
2008
+ items.forEach(item => {
2009
+ totalSize += item.size || 0
2010
+ channelStats[item.channelKey] = (channelStats[item.channelKey] || 0) + 1
2011
+ })
2012
+
2013
+ resolve({
2014
+ totalSize,
2015
+ totalImages: items.length,
2016
+ channelStats
2017
+ })
2018
+ }
1958
2019
 
1959
2020
  request.onerror = () => {
1960
- console.error('IndexedDB初始化失败:', request.error)
1961
- resolve(false)
2021
+ console.error('获取数据库统计失败:', request.error)
2022
+ resolve({ totalSize: 0, totalImages: 0, channelStats: {} })
2023
+ }
2024
+ })
2025
+ }
2026
+
2027
+ // 自动清理
2028
+ async function performAutomaticCleanup() {
2029
+ try {
2030
+ console.log('开始自动清理...')
2031
+
2032
+ // 获取所有图片,按时间排序
2033
+ const allImages = await getAllImagesFromDB()
2034
+ if (allImages.length === 0) return
2035
+
2036
+ // 按频道分组
2037
+ const channelGroups: Record<string, ImageCacheItem[]> = {}
2038
+ allImages.forEach(item => {
2039
+ if (!channelGroups[item.channelKey]) {
2040
+ channelGroups[item.channelKey] = []
2041
+ }
2042
+ channelGroups[item.channelKey].push(item)
2043
+ })
2044
+
2045
+ let cleanedCount = 0
2046
+ let freedSize = 0
2047
+
2048
+ // 清理每个频道超出限制的图片
2049
+ for (const [channelKey, images] of Object.entries(channelGroups)) {
2050
+ if (images.length > MAX_IMAGES_PER_CHANNEL) {
2051
+ // 按时间排序,删除最旧的
2052
+ images.sort((a, b) => a.timestamp - b.timestamp)
2053
+ const toDelete = images.slice(0, images.length - MAX_IMAGES_PER_CHANNEL)
2054
+
2055
+ for (const item of toDelete) {
2056
+ await deleteImageFromDB(item.url)
2057
+ cleanedCount++
2058
+ freedSize += item.size || 0
2059
+
2060
+ // 清理内存中的blob URL
2061
+ if (imageBlobUrls.value[item.url]) {
2062
+ URL.revokeObjectURL(imageBlobUrls.value[item.url])
2063
+ delete imageBlobUrls.value[item.url]
2064
+ }
2065
+ }
2066
+ }
2067
+ }
2068
+
2069
+ console.log(`自动清理完成: 清理了 ${cleanedCount} 张图片,释放了 ${(freedSize / 1024 / 1024).toFixed(2)}MB`)
2070
+
2071
+ // 更新统计
2072
+ currentImageCount -= cleanedCount
2073
+ currentDbSize -= freedSize
2074
+
2075
+ } catch (error) {
2076
+ console.error('自动清理失败:', error)
2077
+ }
2078
+ }
2079
+
2080
+ // 紧急清理 // 激进
2081
+ async function performEmergencyCleanup() {
2082
+ try {
2083
+ console.log('开始紧急清理...')
2084
+
2085
+ // 获取所有图片
2086
+ const allImages = await getAllImagesFromDB()
2087
+ if (allImages.length === 0) return
2088
+
2089
+ // 按时间排序,只保留最新的一部分
2090
+ allImages.sort((a, b) => b.timestamp - a.timestamp)
2091
+ const keepCount = Math.floor(MAX_TOTAL_IMAGES * 0.3) // 只保留30%
2092
+ const toDelete = allImages.slice(keepCount)
2093
+
2094
+ let cleanedCount = 0
2095
+ let freedSize = 0
2096
+
2097
+ for (const item of toDelete) {
2098
+ await deleteImageFromDB(item.url)
2099
+ cleanedCount++
2100
+ freedSize += item.size || 0
2101
+
2102
+ // 清理内存中的blob URL
2103
+ if (imageBlobUrls.value[item.url]) {
2104
+ URL.revokeObjectURL(imageBlobUrls.value[item.url])
2105
+ delete imageBlobUrls.value[item.url]
2106
+ }
1962
2107
  }
1963
2108
 
2109
+ console.log(`紧急清理完成: 清理了 ${cleanedCount} 张图片,释放了 ${(freedSize / 1024 / 1024).toFixed(2)}MB`)
2110
+
2111
+ // 更新统计
2112
+ currentImageCount = keepCount
2113
+ currentDbSize -= freedSize
2114
+
2115
+ } catch (error) {
2116
+ console.error('紧急清理失败:', error)
2117
+ }
2118
+ }
2119
+
2120
+ // 获取所有图片
2121
+ async function getAllImagesFromDB(): Promise<ImageCacheItem[]> {
2122
+ if (!imageDB) return []
2123
+
2124
+ return new Promise((resolve) => {
2125
+ const transaction = imageDB!.transaction([STORE_NAME], 'readonly')
2126
+ const store = transaction.objectStore(STORE_NAME)
2127
+ const request = store.getAll()
2128
+
1964
2129
  request.onsuccess = () => {
1965
- imageDB = request.result
1966
- resolve(true)
2130
+ resolve(request.result || [])
2131
+ }
2132
+
2133
+ request.onerror = () => {
2134
+ console.error('获取所有图片失败:', request.error)
2135
+ resolve([])
2136
+ }
2137
+ })
2138
+ }
2139
+
2140
+ // 清理所有IndexedDB数据 //紧急情况使用
2141
+ async function clearAllIndexedDBData(): Promise<boolean> {
2142
+ return new Promise((resolve) => {
2143
+ try {
2144
+ // 先关闭现有连接
2145
+ if (imageDB) {
2146
+ imageDB.close()
2147
+ imageDB = null
2148
+ }
2149
+
2150
+ // 删除整个数据库
2151
+ const deleteRequest = indexedDB.deleteDatabase(DB_NAME)
2152
+
2153
+ deleteRequest.onsuccess = () => {
2154
+ console.log('IndexedDB数据库已完全清理')
2155
+ currentDbSize = 0
2156
+ currentImageCount = 0
2157
+ resolve(true)
2158
+ }
2159
+
2160
+ deleteRequest.onerror = () => {
2161
+ console.error('清理IndexedDB数据库失败:', deleteRequest.error)
2162
+ resolve(false)
2163
+ }
2164
+
2165
+ deleteRequest.onblocked = () => {
2166
+ console.warn('IndexedDB数据库删除被阻塞,可能有其他连接正在使用')
2167
+ // 等待一段时间后重试
2168
+ setTimeout(() => {
2169
+ resolve(false)
2170
+ }, 5000)
2171
+ }
2172
+ } catch (error) {
2173
+ console.error('清理数据库时出错:', error)
2174
+ resolve(false)
1967
2175
  }
2176
+ })
2177
+ }
2178
+
2179
+ // IndexedDB初始化
2180
+ async function initImageDB(): Promise<boolean> {
2181
+ try {
2182
+ // 首先尝试打开数据库
2183
+ const success = await openDatabase()
2184
+ if (!success) {
2185
+ console.warn('数据库打开失败,尝试清理后重新初始化')
2186
+ await clearAllIndexedDBData()
2187
+ return await openDatabase()
2188
+ }
2189
+
2190
+ // 数据库打开成功,进行初始健康检查
2191
+ setTimeout(async () => {
2192
+ const stats = await getDatabaseStats()
2193
+ console.log('数据库初始状态:', {
2194
+ 大小: `${(stats.totalSize / 1024 / 1024).toFixed(2)}MB`,
2195
+ 图片数量: stats.totalImages,
2196
+ 频道分布: stats.channelStats
2197
+ })
2198
+
2199
+ // 如果初始状态就超过限制,执行清理
2200
+ if (stats.totalSize > MAX_DB_SIZE * 0.9 || stats.totalImages > MAX_TOTAL_IMAGES * 0.9) {
2201
+ console.warn('数据库初始状态接近限制,执行清理')
2202
+ await performAutomaticCleanup()
2203
+ }
2204
+ }, 1000)
2205
+
2206
+ return true
2207
+ } catch (error) {
2208
+ console.error('IndexedDB初始化出错:', error)
2209
+ return false
2210
+ }
2211
+ }
1968
2212
 
1969
- request.onupgradeneeded = (event) => {
1970
- const db = (event.target as IDBOpenDBRequest).result
2213
+ // 打开数据库的内部函数
2214
+ async function openDatabase(): Promise<boolean> {
2215
+ return new Promise((resolve) => {
2216
+ try {
2217
+ const request = indexedDB.open(DB_NAME, DB_VERSION)
2218
+
2219
+ request.onerror = () => {
2220
+ console.error('IndexedDB打开失败:', request.error)
2221
+ resolve(false)
2222
+ }
2223
+
2224
+ request.onsuccess = () => {
2225
+ imageDB = request.result
2226
+
2227
+ // 添加错误处理
2228
+ imageDB.onerror = (event) => {
2229
+ console.error('IndexedDB运行时错误:', event)
2230
+ }
2231
+
2232
+ // 添加版本变更处理
2233
+ imageDB.onversionchange = () => {
2234
+ console.warn('IndexedDB版本变更,关闭连接')
2235
+ imageDB?.close()
2236
+ imageDB = null
2237
+ }
2238
+
2239
+ resolve(true)
2240
+ }
2241
+
2242
+ request.onupgradeneeded = (event) => {
2243
+ const db = (event.target as IDBOpenDBRequest).result
2244
+
2245
+ // 创建对象存储
2246
+ if (!db.objectStoreNames.contains(STORE_NAME)) {
2247
+ const store = db.createObjectStore(STORE_NAME, { keyPath: 'url' })
2248
+ store.createIndex('channelKey', 'channelKey', { unique: false })
2249
+ store.createIndex('timestamp', 'timestamp', { unique: false })
2250
+ store.createIndex('size', 'size', { unique: false })
2251
+ console.log('IndexedDB对象存储创建完成')
2252
+ }
2253
+ }
1971
2254
 
1972
- // 创建对象存储
1973
- if (!db.objectStoreNames.contains(STORE_NAME)) {
1974
- const store = db.createObjectStore(STORE_NAME, { keyPath: 'url' })
1975
- store.createIndex('channelKey', 'channelKey', { unique: false })
1976
- store.createIndex('timestamp', 'timestamp', { unique: false })
2255
+ request.onblocked = () => {
2256
+ console.warn('IndexedDB打开被阻塞')
2257
+ resolve(false)
1977
2258
  }
2259
+ } catch (error) {
2260
+ console.error('打开数据库时出错:', error)
2261
+ resolve(false)
1978
2262
  }
1979
2263
  })
1980
2264
  }
@@ -2003,20 +2287,60 @@ async function getImageFromDB(url: string): Promise<ImageCacheItem | null> {
2003
2287
  async function saveImageToDB(item: ImageCacheItem): Promise<boolean> {
2004
2288
  if (!imageDB) return false
2005
2289
 
2006
- return new Promise((resolve) => {
2007
- const transaction = imageDB!.transaction([STORE_NAME], 'readwrite')
2008
- const store = transaction.objectStore(STORE_NAME)
2009
- const request = store.put(item)
2290
+ try {
2291
+ // 检查单张图片大小
2292
+ if (item.size > MAX_IMAGE_SIZE) {
2293
+ console.warn(`图片过大,跳过缓存: ${(item.size / 1024 / 1024).toFixed(2)}MB > ${(MAX_IMAGE_SIZE / 1024 / 1024).toFixed(2)}MB`)
2294
+ return false
2295
+ }
2010
2296
 
2011
- request.onsuccess = () => {
2012
- resolve(true)
2297
+ // 执行健康检查
2298
+ await checkDatabaseHealth()
2299
+
2300
+ // 检查是否会超过限制
2301
+ if (currentDbSize + item.size > MAX_DB_SIZE) {
2302
+ console.warn('添加图片会超过数据库大小限制,执行清理')
2303
+ await performAutomaticCleanup()
2304
+
2305
+ // 清理后再次检查
2306
+ if (currentDbSize + item.size > MAX_DB_SIZE) {
2307
+ console.warn('清理后仍会超过限制,跳过此图片')
2308
+ return false
2309
+ }
2013
2310
  }
2014
2311
 
2015
- request.onerror = () => {
2016
- console.error('保存图片到IndexedDB失败:', request.error)
2017
- resolve(false)
2312
+ if (currentImageCount >= MAX_TOTAL_IMAGES) {
2313
+ console.warn('图片数量已达上限,执行清理')
2314
+ await performAutomaticCleanup()
2315
+
2316
+ // 清理后再次检查
2317
+ if (currentImageCount >= MAX_TOTAL_IMAGES) {
2318
+ console.warn('清理后仍达上限,跳过此图片')
2319
+ return false
2320
+ }
2018
2321
  }
2019
- })
2322
+
2323
+ return new Promise((resolve) => {
2324
+ const transaction = imageDB!.transaction([STORE_NAME], 'readwrite')
2325
+ const store = transaction.objectStore(STORE_NAME)
2326
+ const request = store.put(item)
2327
+
2328
+ request.onsuccess = () => {
2329
+ // 更新统计
2330
+ currentDbSize += item.size
2331
+ currentImageCount += 1
2332
+ resolve(true)
2333
+ }
2334
+
2335
+ request.onerror = () => {
2336
+ console.error('保存图片到IndexedDB失败:', request.error)
2337
+ resolve(false)
2338
+ }
2339
+ })
2340
+ } catch (error) {
2341
+ console.error('保存图片时出错:', error)
2342
+ return false
2343
+ }
2020
2344
  }
2021
2345
 
2022
2346
  // 从IndexedDB删除图片
@@ -2118,22 +2442,10 @@ async function cacheImage(channelKey: string, originalUrl: string): Promise<stri
2118
2442
  const byteArray = new Uint8Array(byteNumbers)
2119
2443
  const blob = new Blob([byteArray], { type: contentType })
2120
2444
 
2121
- // 检查频道缓存数量限制
2122
- const channelImages = await getChannelImagesFromDB(channelKey)
2123
-
2124
- if (channelImages.length >= maxImagesPerChannel) {
2125
- // 清理最旧的图片缓存
2126
- const sortedImages = channelImages.sort((a, b) => a.timestamp - b.timestamp)
2127
- const toDelete = sortedImages.slice(0, channelImages.length - maxImagesPerChannel + 1)
2128
-
2129
- for (const item of toDelete) {
2130
- await deleteImageFromDB(item.url)
2131
- // 清理内存中的blob URL
2132
- if (imageBlobUrls.value[item.url]) {
2133
- URL.revokeObjectURL(imageBlobUrls.value[item.url])
2134
- delete imageBlobUrls.value[item.url]
2135
- }
2136
- }
2445
+ // 检查blob大小
2446
+ if (blob.size > MAX_IMAGE_SIZE) {
2447
+ console.warn(`图片过大,跳过缓存: ${(blob.size / 1024 / 1024).toFixed(2)}MB`)
2448
+ return null
2137
2449
  }
2138
2450
 
2139
2451
  // 创建缓存项
@@ -2369,7 +2681,7 @@ function handleMessageEvent(messageEvent: any) {
2369
2681
  chatData.value = { ...chatData.value }
2370
2682
  }
2371
2683
 
2372
- // 处理机器人发送消息成功事件(通过前端发送消息API触发)
2684
+ // 处理机器人发送消息成功事件
2373
2685
  function handleBotMessageSentEvent(sentEvent: any) {
2374
2686
  const channelKey = `${sentEvent.selfId}:${sentEvent.channelId}`
2375
2687
  if (!chatData.value.messages[channelKey]) {
@@ -2436,7 +2748,7 @@ function handleBotMessageSentEvent(sentEvent: any) {
2436
2748
  chatData.value = { ...chatData.value }
2437
2749
  }
2438
2750
 
2439
- // 处理机器人消息事件(通过before-send事件监听触发)
2751
+ // 处理机器人消息事件
2440
2752
  function handleBotMessageEvent(botMessageEvent: any) {
2441
2753
  // 更新机器人信息
2442
2754
  if (!chatData.value.bots[botMessageEvent.selfId]) {
@@ -2562,7 +2874,7 @@ function handleBotMessageEvent(botMessageEvent: any) {
2562
2874
  chatData.value = { ...chatData.value }
2563
2875
  }
2564
2876
 
2565
- // 监听消息变化,只在切换频道时自动滚动到底部
2877
+ // 监听消息变化
2566
2878
  watch(currentMessages, (newMessages, oldMessages) => {
2567
2879
  // 只有在切换频道时(消息数组完全不同)才自动滚动
2568
2880
  if (oldMessages.length === 0 && newMessages.length > 0) {
@@ -2830,6 +3142,18 @@ onMounted(async () => {
2830
3142
  const dbInitialized = await initImageDB()
2831
3143
  if (!dbInitialized) {
2832
3144
  console.warn('IndexedDB初始化失败,图片缓存功能将不可用')
3145
+ } else {
3146
+ console.log('IndexedDB初始化成功')
3147
+
3148
+ // 启动时进行健康检查
3149
+ setTimeout(async () => {
3150
+ await checkDatabaseHealth()
3151
+ }, 2000) // 延迟2秒,避免影响页面加载
3152
+
3153
+ // 设置定期健康检查(每5分钟)
3154
+ setInterval(async () => {
3155
+ await checkDatabaseHealth()
3156
+ }, 5 * 60 * 1000)
2833
3157
  }
2834
3158
 
2835
3159
  // 首先加载插件配置
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{defineComponent as Q,ref as f,onMounted as Ne,h as d,computed as O,watch as nt,nextTick as re,onUnmounted as Gt,createElementBlock as p,openBlock as v,normalizeStyle as Oe,normalizeClass as F,createElementVNode as c,createCommentVNode as G,Fragment as P,renderList as oe,createBlock as he,unref as me,toDisplayString as x,withDirectives as st,createTextVNode as Pe,vShow as Qt,withModifiers as lt,withKeys as Zt,vModelText as Et,resolveComponent as ea}from"vue";import{receive as Re,send as _,icons as ta}from"@koishijs/client";const aa={class:"bot-list"},na={class:"bot-items"},sa=["onClick","onContextmenu"],la={class:"bot-avatar"},ra={key:1,class:"avatar-placeholder"},oa={class:"bot-info"},ca={class:"bot-name"},ia={class:"bot-platform"},ua={class:"channel-list"},da={key:0,class:"empty-state"},fa={key:1,class:"channel-items"},ha=["data-channel-id","onClick","onContextmenu"],ma={class:"channel-info"},va={class:"channel-name"},ga={class:"channel-type"},ya=["onMousedown","onTouchstart","title"],pa={class:"message-area"},wa={class:"panel-header"},Ia={key:0,class:"empty-state"},xa={key:1,class:"message-content"},Ca={class:"message-avatar"},ka={key:1,class:"avatar-placeholder"},ba={class:"message-content-wrapper"},_a={class:"message-header"},$a={class:"message-username"},Sa={class:"message-time"},Ba={key:0,class:"message-quote"},La={class:"quote-header"},Ta={class:"quote-avatar"},qa={key:1,class:"avatar-placeholder"},Da={class:"quote-username"},Ua={class:"quote-time"},ja={class:"quote-content"},Ka={class:"message-text"},Na={class:"message-input"},Oa={key:0,class:"image-preview-container"},Pa=["src","alt"],Ra=["onClick"],Aa={class:"input-row"},Ma={class:"input-actions"},za=["placeholder","disabled"],Xa=["disabled"],rt=200,Ha=100*1024*1024,Ae=50,Fa="ChatImageCache",Ya=1,R="images",A=80,Wa=Q({__name:"index",setup(Z){function Y(e){try{return new URL(e).protocol==="file:"}catch{return false}}const E=Q({props:{src:{type:String,required:true},alt:{type:String,default:"头像"},channelKey:{type:String,required:true}},setup(e){const a=f("loading"),t=f(e.src),n=f(""),l=async()=>{try{a.value="loading";const o=await je(e.channelKey,e.src);if(o){t.value=o,a.value="loaded";return}const r=new Image;r.crossOrigin="anonymous",r.referrerPolicy="no-referrer",r.draggable=false;const i=new Promise((g,y)=>{r.onload=()=>g(),r.onerror=()=>y(new Error("Direct load failed")),r.src=e.src}),h=new Promise((g,y)=>{setTimeout(()=>y(new Error("Timeout")),3e3)});try{await Promise.race([i,h]),t.value=e.src,a.value="loaded",se(e.channelKey,e.src).catch(g=>{console.warn("异步缓存头像失败:",g)})}catch{await s()}}catch(o){console.error("头像加载失败:",o),a.value="error",n.value="头像加载失败"}},s=async()=>{try{a.value="caching";const o=await se(e.channelKey,e.src);if(o)t.value=o,a.value="loaded";else throw new Error("缓存系统加载失败")}catch(o){console.error("缓存系统加载头像失败:",o),a.value="error",n.value=(o==null?void 0:o.message)||"缓存加载失败"}};return Ne(()=>{l()}),()=>{switch(a.value){case"loading":case"caching":return d("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase());case"loaded":return d("img",{src:t.value,alt:e.alt,draggable:false,style:{width:"100%",height:"100%","object-fit":"cover"}});case"error":return d("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase());default:return d("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase())}}}}),ce=Q({props:{src:{type:String,required:true},alt:{type:String,default:"图片"},filename:{type:String,default:""},channelKey:{type:String,required:true}},setup(e){const a=f("loading"),t=f(e.src),n=f(""),l=f(null),s=async()=>{try{a.value="loading";const r=await je(e.channelKey,e.src);if(r){t.value=r,a.value="loaded";return}if(Y(e.src)){console.log("ImageComponent: 检测到本地文件,使用代理请求:",e.src),await o();return}const i=new Image;i.crossOrigin="anonymous",i.referrerPolicy="no-referrer",i.draggable=false;const h=new Promise((y,q)=>{i.onload=()=>y(),i.onerror=()=>q(new Error("Direct load failed")),i.src=e.src}),g=new Promise((y,q)=>{setTimeout(()=>q(new Error("Timeout")),3e3)});try{await Promise.race([h,g]),t.value=e.src,a.value="loaded",se(e.channelKey,e.src).catch(y=>{console.warn("异步缓存图片失败:",y)})}catch{await o()}}catch(r){console.error("图片加载失败:",r),a.value="error",n.value="图片加载失败"}},o=async()=>{try{a.value="caching";const r=await se(e.channelKey,e.src);if(r)t.value=r,a.value="loaded";else throw new Error("缓存系统加载失败")}catch(r){console.error("缓存系统加载图片失败:",r),a.value="error",n.value=(r==null?void 0:r.message)||"缓存加载失败"}};return Ne(()=>{s()}),()=>{switch(a.value){case"loading":return d("div",{class:"message-image-loading"},"加载中...");case"caching":return d("div",{class:"message-image-loading"},"[图片加载缓存中...]");case"loaded":return d("img",{src:t.value,alt:e.alt,class:"message-image",loading:"lazy",ref:l,draggable:false,style:{"max-width":"400px","max-height":"200px",width:"auto",height:"auto","object-fit":"contain"}});case"error":return d("div",{class:"message-image-error"},["图片加载失败",d("br"),d("small",e.filename||e.alt||"未知图片"),d("br"),d("small",{style:"color: #ff9800;"},n.value)]);default:return d("div",{class:"message-image-error"},"未知状态")}}}}),be=Q({props:{data:{type:String,required:true},channelKey:{type:String,required:true}},setup(e){const t=(()=>{try{const l=JSON.parse(e.data);if(l.meta&&l.meta.detail_1){const s=l.meta.detail_1;return{type:"share_card",title:s.title||l.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:l}}catch(l){return console.error("解析JSON数据失败:",l),{type:"error",error:"无法解析的JSON数据"}}})(),n=()=>{t.type==="share_card"&&t.url&&window.open(t.url,"_blank","noopener,noreferrer")};return()=>t.type==="share_card"&&t.preview?d("img",{src:t.preview,alt:t.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:t.url?"pointer":"default"},title:t.url?`点击打开: ${t.title||"链接"}`:t.title,onError:l=>{const o=l.target.parentElement;o&&(o.style.display="none")}}):t.type==="error"?d("div",{class:"message-json-error"},[d("span",{class:"json-error-text"},t.error),d("details",{class:"json-raw-data"},[d("summary","查看原始数据"),d("pre",{class:"json-raw-content"},e.data)])]):d("div",{class:"message-json-raw"},[d("div",{class:"json-label"},"[JSON数据]"),d("details",{class:"json-raw-data"},[d("summary","查看详情"),d("pre",{class:"json-raw-content"},JSON.stringify(t.data,null,2))])])}}),ct=Q({props:{element:{type:Object,required:true},channelKey:{type:String,required:true}},setup(e){const a=f(false),t=()=>{a.value=!a.value},n=()=>{if(!e.element.children||e.element.children.length===0)return{previews:[],messageCount:0};const s=e.element.children.filter(i=>i.type==="message"),o=s.length;return{previews:s.slice(0,3).map(i=>{var y,q;const h=((y=i.attrs)==null?void 0:y.nickname)||"用户";let g="";if(i.children&&i.children.length>0){const B=i.children[0];B.type==="text"?(g=(((q=B.attrs)==null?void 0:q.content)||"").substring(0,20),g.length>15&&(g+="...")):B.type==="img"?g="[图片]":B.type==="video"?g="[视频]":g=`[${B.type}]`}return`${h}:${g}`}),messageCount:o}},l=(s,o)=>{var h,g,y;const r=((h=s.attrs)==null?void 0:h.nickname)||"用户",i=((g=s.attrs)==null?void 0:g.userId)||"unknown";return d("div",{key:o,class:"forwarded-message-item"},[d("div",{class:"forwarded-message-header"},[d("span",{class:"forwarded-message-nickname"},r),d("span",{class:"forwarded-message-userid"},`(${i})`)]),d("div",{class:"forwarded-message-content"},((y=s.children)==null?void 0:y.map((q,B)=>d(ve,{key:B,element:q,channelKey:e.channelKey})))||[])])};return()=>{var r;const{previews:s,messageCount:o}=n();return d("div",{class:"forward-message-container"},[d("div",{class:"forward-message-preview",onClick:t},[d("div",{class:"forward-message-title"},"聊天记录"),...s.map((i,h)=>d("div",{key:h,class:"forward-message-preview-item"},i)),d("div",{class:"forward-message-footer"},[d("span",{class:"forward-message-count"},`查看${o}条转发消息`),d("span",{class:"forward-message-toggle"},a.value?"▲":"▼")])]),a.value&&d("div",{class:"forward-message-expanded"},((r=e.element.children)==null?void 0:r.filter(i=>i.type==="message").map((i,h)=>l(i,h)))||[])])}}}),ve=Q({props:{element:{type:Object,required:true},channelKey:{type:String,required:true}},setup(e){const a=t=>{var n,l,s,o,r,i;switch(t.type){case"text":return d("span",{class:"message-text-content"},t.attrs.content||"");case"forward":return d("span",{class:"message-text-content"},`[转发消息 ${t.attrs.id}]`||"[转发消息]");case"img":case"image":const h=t.attrs.src||t.attrs.url||t.attrs.file;return h&&Y(h)?console.log("检测到本地文件路径:",h):h!=null&&h.startsWith("http")?console.log("检测到网络图片:",h):console.log("检测到其他类型图片URL:",h),d("div",{class:"message-image-container"},[d(ce,{src:h,alt:t.attrs.summary||"图片",filename:t.attrs.filename||t.attrs.summary||"",channelKey:e.channelKey})]);case"mface":const g=t.attrs.src||t.attrs.url||t.attrs.file;return g&&Y(g)&&console.log("检测到本地表情文件路径:",g),d("div",{class:"message-image-container"},[d(ce,{src:g,alt:t.attrs.summary||"表情",filename:t.attrs.emojiId||t.attrs.summary||"",channelKey:e.channelKey})]);case"face":if((l=(n=t.children[0])==null?void 0:n.attrs)!=null&&l.src){const y=((o=(s=t.children[0])==null?void 0:s.attrs)==null?void 0:o.src)||((i=(r=t.children[0])==null?void 0:r.attrs)==null?void 0:i.url);return d("div",{class:"message-image-container"},[d(ce,{src:y,alt:t.attrs.name||t.attrs.id||"[表情]",filename:t.attrs.name||t.attrs.id||"[表情]",channelKey:e.channelKey})])}else return d("span",{class:"message-text-content"},`[${t.attrs.name||t.attrs.id}]`||"[表情]");case"at":return d("span",{class:"message-at",title:t.attrs.name},`${t.attrs.name||t.attrs.id}`);case"json":return d("div",{class:"message-image-container"},[d(be,{data:t.attrs.data||"",channelKey:e.channelKey})]);case"p":if(t.children&&t.children.length>0){const y=t.children.map((q,B)=>d(ve,{key:B,element:q,channelKey:e.channelKey}));return d("div",{class:"message-paragraph"},y)}else return d("div",{class:"message-paragraph"},"");case"figure":return d(ct,{element:t,channelKey:e.channelKey});default:return d("span",{class:"message-unknown",title:`未知消息类型: ${t.type}`},t.attrs.content||`[${t.type}]`)}};return()=>a(e.element)}}),u=f({bots:{},channels:{},messages:{}}),D=f({}),ie=f({maxMessagesPerChannel:1e3,keepMessagesOnClear:50,loggerinfo:false,blockedPlatforms:[],chatContainerHeight:80}),b=f({});let _e=0;function Me(e){return e.size||0}function ge(e){_e+=e,ie.value.loggerinfo&&console.log(`内存使用量变化: ${e>0?"+":""}${(e/1024/1024).toFixed(2)}MB, 总计: ${(_e/1024/1024).toFixed(2)}MB`)}function ze(e=10){const a=Object.entries(b.value);if(a.length<=e)return;const t=a.slice(0,a.length-e);let n=0;t.forEach(([l,s])=>{URL.revokeObjectURL(s),delete b.value[l],n+=500*1024,ie.value.loggerinfo&&console.log("清理旧blob URL:",l)}),ge(-n)}function $e(){Object.keys(b.value).length>Ae&&ze(Math.floor(Ae*.7)),_e>Ha&&ze(Math.floor(Ae*.5))}let S=null;const m=f(""),C=f(""),ue=f(""),U=f([]),J=f(false),Se=f(),L=f(false),W=f("bots"),M=f(null),ee=f(null),Be=f(false),V=f({show:false,text:""}),$=f(),de=f(),Le=f(false),ye=f(false),te=f(false),z=f(""),j=f({x:0,y:0}),T=f({x:0,y:0}),Xe=f({x:0,y:0}),Te=f({x:0,y:0}),qe=f(0),K=f(null),ae=f(false),w=f(null),I=f({show:false,x:0,y:0,type:null,targetId:"",isSecondClick:false}),X=f(new Set),H=f(new Set),it=O(()=>Object.values(u.value.bots).sort((a,t)=>{const n=X.value.has(a.selfId),l=X.value.has(t.selfId);return n&&!l?-1:!n&&l?1:0})),ut=O(()=>!m.value||!u.value.channels[m.value]?[]:Object.values(u.value.channels[m.value]).sort((a,t)=>{const n=H.value.has(`${m.value}:${a.id}`),l=H.value.has(`${m.value}:${t.id}`);return n&&!l?-1:!n&&l?1:0})),He=O(()=>{if(!m.value||!C.value)return[];const e=`${m.value}:${C.value}`,a=u.value.messages[e]||[];return a.filter(t=>t.quote),a}),dt=O(()=>{var a;if(!m.value||!C.value)return"";const e=u.value.channels[m.value];return((a=e==null?void 0:e[C.value])==null?void 0:a.name)||""}),pe=O(()=>!m.value||!C.value?"":`${m.value}:${C.value}`),Fe=O(()=>m.value&&C.value&&(ue.value.trim()||U.value.length>0)&&!te.value),ft=O(()=>m.value&&C.value&&!te.value),ht=O(()=>{if(!L.value)return"";switch(W.value){case"channels":return"show-channels";case"messages":return"show-messages";default:return""}}),mt=O(()=>L.value?"输入消息...(屏幕左滑返回)":"输入消息..."),vt=O(()=>{if(L.value){const e=ie.value.chatContainerHeight||80,a=100-e-19;return{height:`${e}vh`,marginTop:`${a}vh`}}return{}});function gt(e){m.value=e,C.value="",L.value&&(W.value="channels")}function yt(e,a){if(e.preventDefault(),e.stopPropagation(),I.value.show&&I.value.type==="bot"&&I.value.targetId===a){N();return}Ye(e,"bot",a)}function pt(e,a){if(e.preventDefault(),e.stopPropagation(),I.value.show&&I.value.type==="channel"&&I.value.targetId===a){N();return}Ye(e,"channel",a)}function Ye(e,a,t){let s=e.clientX,o=e.clientY;s+180>window.innerWidth&&(s=window.innerWidth-180-10),o+80>window.innerHeight&&(o=window.innerHeight-80-10),I.value={show:true,x:s,y:o,type:a,targetId:t,isSecondClick:false},document.addEventListener("click",N,{once:true}),document.addEventListener("keydown",We)}function N(){I.value.show=false,document.removeEventListener("click",N),document.removeEventListener("keydown",We)}function We(e){e.key==="Escape"&&I.value.show&&N()}async function wt(e){X.value.has(e)?X.value.delete(e):X.value.add(e),await _("set-pinned-bots",{pinnedBots:Array.from(X.value)}),N()}async function It(e){const a=`${m.value}:${e}`;H.value.has(a)?H.value.delete(a):H.value.add(a),await _("set-pinned-channels",{pinnedChannels:Array.from(H.value)}),N()}async function xt(e){try{const a=await _("delete-bot-data",{selfId:e});if(a.success){const t=Object.keys(u.value.messages).filter(n=>n.startsWith(`${e}:`));for(const n of t)delete u.value.messages[n],delete D.value[n],await ke(n);delete u.value.bots[e],delete u.value.channels[e],m.value===e&&(m.value="",C.value=""),k(a.message||"已删除该机器人的所有数据","success")}else throw new Error(a.error||"删除失败")}catch(a){console.error("删除机器人数据失败:",a),k("删除失败: "+((a==null?void 0:a.message)||String(a)),"error")}N()}async function Ct(e){try{const a=await _("delete-channel-data",{selfId:m.value,channelId:e});if(a.success){const t=`${m.value}:${e}`;delete u.value.messages[t],delete D.value[t],u.value.channels[m.value]&&delete u.value.channels[m.value][e],await ke(t),C.value===e&&(C.value=""),k(a.message||"已删除该频道的所有数据","success")}else throw new Error(a.error||"删除失败")}catch(a){console.error("删除频道数据失败:",a),k("删除失败: "+((a==null?void 0:a.message)||String(a)),"error")}N()}async function kt(e){C.value=e,ye.value=false,L.value&&(W.value="messages"),m.value&&await Xt(m.value,e),re(()=>{ne(),!L.value&&de.value&&de.value.focus()})}async function Je(){if(!Fe.value)return;const e=ue.value.trim();if(!e&&U.value.length===0)return;te.value=true;const a=[...U.value];try{const t=await _("send-message",{selfId:m.value,channelId:C.value,content:e,images:a.map(n=>({tempId:n.tempId,filename:n.filename}))});if(t.success){if(ue.value="",a.forEach(n=>{URL.revokeObjectURL(n.preview)}),U.value=[],J.value=false,t.tempImageIds&&t.tempImageIds.length>0)try{await _("cleanup-temp-images",{tempImageIds:t.tempImageIds}),console.log("临时图片清理完成:",t.tempImageIds)}catch(n){console.warn("清理临时图片失败:",n)}}else console.error("消息发送失败:",t.error),k("发送失败: "+t.error,"error")}catch(t){console.error("发送消息时出错:",t),k("发送失败: "+((t==null?void 0:t.message)||String(t)),"error")}finally{te.value=false}}function bt(){J.value=!J.value}function _t(){Se.value&&Se.value.click(),J.value=false}async function $t(e){const a=e.target,t=a.files;if(!(!t||t.length===0)){for(const n of Array.from(t))await Ve(n);a.value=""}}async function St(e){var t;const a=(t=e.clipboardData)==null?void 0:t.items;if(a){for(const n of Array.from(a))if(n.type.startsWith("image/")){e.preventDefault();const l=n.getAsFile();l&&await Ve(l)}}}async function Ve(e){try{if(e.size>10*1024*1024){k("图片文件过大,请选择小于10MB的图片","error");return}if(!e.type.startsWith("image/")){k("请选择图片文件","error");return}const a=await Lt(e),t=URL.createObjectURL(e),n=await _("upload-image",{file:a,filename:e.name,mimeType:e.type});n.success?U.value.push({tempId:n.tempId,filename:e.name,preview:t,size:e.size}):(URL.revokeObjectURL(t),k("图片上传失败: "+n.error,"error"))}catch(a){console.error("上传图片失败:",a),k("图片上传失败: "+((a==null?void 0:a.message)||String(a)),"error")}}async function Bt(e){try{const a=U.value.findIndex(t=>t.tempId===e);if(a!==-1){const t=U.value[a];URL.revokeObjectURL(t.preview),U.value.splice(a,1)}await _("delete-temp-image",{tempId:e})}catch(a){console.error("删除图片失败:",a)}}function Lt(e){return new Promise((a,t)=>{const n=new FileReader;n.onload=()=>a(n.result),n.onerror=t,n.readAsDataURL(e)})}function Ge(e){const a=e.target;a.closest(".input-actions")||(J.value=false),a.closest(".context-menu")||N()}function Qe(e){return new Date(e).toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit"})}function Tt(e){if(typeof e=="number")switch(e){case 0:return"文本";case 1:return"私聊";default:return"未知"}return String(e)}function ne(){$.value&&($.value.scrollTop=$.value.scrollHeight,Le.value=false,ye.value=false)}function we(){if($.value){const{scrollTop:e,scrollHeight:a,clientHeight:t}=$.value,l=a-(e+t)<=50,s=!l;Le.value=s,l?ye.value=false:ye.value=true}}function De(){if(!$.value)return true;const{scrollTop:e,scrollHeight:a,clientHeight:t}=$.value;return a-(e+t)<=200}function Ue(e){var n;if(!m.value)return 0;const a=`${m.value}:${e}`,t=D.value[a];return t!==void 0?t:((n=u.value.messages[a])==null?void 0:n.length)||0}function Ze(e,a){e.preventDefault(),e.stopPropagation();const t="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:t,y:n},T.value={x:t,y:n},ae.value=false;const s=e.target.getBoundingClientRect();Xe.value={x:s.left,y:s.top},Te.value={x:t-s.left,y:n-s.top},K.value=window.setTimeout(()=>{if(qe.value>0){ae.value=true,z.value=a;const o=e.target,r=o.cloneNode(true);r.classList.add("dragging-clone"),r.style.position="fixed",r.style.zIndex="1000",r.style.pointerEvents="none";const i=o.getBoundingClientRect();r.style.left=`${i.left}px`,r.style.top=`${i.top}px`,r.style.width=`${i.width}px`,r.style.height=`${i.height}px`,document.body.appendChild(r),w.value=r,document.body.style.userSelect="none",document.body.style.cursor="grabbing",document.body.classList.add("dragging-bubble-global"),Ut(j.value.x,j.value.y)}},60),document.addEventListener("mousemove",Ie),document.addEventListener("mouseup",xe),document.addEventListener("touchmove",Ie),document.addEventListener("touchend",xe)}function Ie(e){if(!ae.value||!w.value)return;e.preventDefault();const a="touches"in e?e.touches[0].clientX:e.clientX,t="touches"in e?e.touches[0].clientY:e.clientY;T.value={x:a,y:t};const n=T.value.x-j.value.x,l=T.value.y-j.value.y,s=Math.sqrt(n*n+l*l),o=Math.max(.3,1-s/(A*2)),r=Math.max(.8,1-s/(A*3)),i=s>A,h=T.value.x-Te.value.x,g=T.value.y-Te.value.y;w.value.style.left=`${h}px`,w.value.style.top=`${g}px`,w.value.style.transform=`scale(${r})`,w.value.style.opacity=`${o}`,w.value.style.backgroundColor=i?"#f44336":"#2196f3",w.value.style.boxShadow=i?"0 4px 12px rgba(244, 67, 54, 0.4)":"0 4px 12px rgba(33, 150, 243, 0.4)",i?w.value.classList.add("will-delete"):w.value.classList.remove("will-delete")}function xe(e){if(K.value&&(clearTimeout(K.value),K.value=null),K.value&&(clearTimeout(K.value),K.value=null),!ae.value||!z.value){Ce();return}const a=z.value;if(Math.sqrt(Math.pow(T.value.x-j.value.x,2)+Math.pow(T.value.y-j.value.y,2))>A)Dt(a),Ce();else if(w.value){w.value.style.transition="all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)";const n=document.querySelector(`[data-channel-id="${a}"] .channel-message-count`);if(n){const l=n.getBoundingClientRect();w.value.style.left=`${l.left}px`,w.value.style.top=`${l.top}px`,w.value.style.transform="scale(1)",w.value.style.opacity="1",w.value.style.backgroundColor="#2196f3",w.value.style.boxShadow="0 4px 12px rgba(33, 150, 243, 0.4)"}setTimeout(()=>{Ce()},300)}else Ce()}function Ce(){K.value&&(clearTimeout(K.value),K.value=null),z.value="",j.value={x:0,y:0},T.value={x:0,y:0},Xe.value={x:0,y:0},qe.value=0,ae.value=false,document.removeEventListener("mousemove",Ie),document.removeEventListener("mouseup",xe),document.removeEventListener("touchmove",Ie),document.removeEventListener("touchend",xe),document.body.style.userSelect="",document.body.style.cursor="",document.body.classList.remove("dragging-bubble-global"),w.value&&w.value.parentNode&&(w.value.parentNode.removeChild(w.value),w.value=null),jt()}function qt(e){return z.value===e&&ae.value?{visibility:"hidden",pointerEvents:"none",transition:"none"}:{}}function Ee(e){if(z.value!==e)return 0;const a=T.value.x-j.value.x,t=T.value.y-j.value.y;return Math.sqrt(a*a+t*t)}async function Dt(e){if(m.value)try{const a=`${m.value}:${e}`,t=Ue(e),n=ie.value.keepMessagesOnClear;if(n>0&&t<=n){k("当前消息还很少诶~ 无需清理","success");return}const l=await _("clear-channel-history",{selfId:m.value,channelId:e});if(l.success)if(l.clearedCount&&l.clearedCount>0){if(u.value.messages[a]){const o=[...u.value.messages[a]].sort((r,i)=>r.timestamp-i.timestamp);u.value.messages[a]=o.slice(-l.keptCount)}D.value[a]=l.keptCount,await ke(a),k(`历史记录已清理,清理了 ${l.clearedCount} 条消息,保留最新 ${l.keptCount} 条`,"success")}else n===0?(u.value.messages[a]&&(u.value.messages[a]=[]),D.value[a]=0,await ke(a),k("历史记录已清理,所有消息已删除","success")):k("当前消息还很少诶~ 无需清理","success");else console.error("清理历史记录失败:",l.error),k("清理失败: "+l.error,"error")}catch(a){console.error("清理历史记录时出错:",a),k("清理失败: "+((a==null?void 0:a.message)||String(a)),"error")}}function k(e,a="success"){const t=document.createElement("div");t.className=`notification ${a}`,t.textContent=e;let n="#4caf50";switch(a){case"info":n="#2196f3";break;case"warn":n="#ff9800";break;case"error":n="#f44336";break;case"success":n="#4caf50";break}t.style.cssText=`
1
+ import{defineComponent as Q,ref as f,onMounted as Pe,h as d,computed as R,watch as dt,nextTick as oe,onUnmounted as oa,createElementBlock as y,openBlock as m,normalizeStyle as Me,normalizeClass as W,createElementVNode as i,createCommentVNode as Z,Fragment as z,renderList as ce,createBlock as ve,unref as ge,toDisplayString as C,withDirectives as ft,createTextVNode as He,vShow as ca,withModifiers as ht,withKeys as ia,vModelText as ua,resolveComponent as da}from"vue";import{receive as Fe,send as S,icons as fa}from"@koishijs/client";const ha={class:"bot-list"},ma={class:"bot-items"},va=["onClick","onContextmenu"],ga={class:"bot-avatar"},ya={key:1,class:"avatar-placeholder"},pa={class:"bot-info"},wa={class:"bot-name"},Ia={class:"bot-platform"},xa={class:"channel-list"},Ca={key:0,class:"empty-state"},ka={key:1,class:"channel-items"},ba=["data-channel-id","onClick","onContextmenu"],_a={class:"channel-info"},$a={class:"channel-name"},Sa={class:"channel-type"},Ba=["onMousedown","onTouchstart","title"],Da={class:"message-area"},Ta={class:"panel-header"},La={key:0,class:"empty-state"},qa={key:1,class:"message-content"},Ua={class:"message-avatar"},Ka={key:1,class:"avatar-placeholder"},ja={class:"message-content-wrapper"},Aa={class:"message-header"},Na={class:"message-username"},Oa={class:"message-time"},Ra={key:0,class:"message-quote"},za={class:"quote-header"},Pa={class:"quote-avatar"},Ma={key:1,class:"avatar-placeholder"},Ha={class:"quote-username"},Fa={class:"quote-time"},Xa={class:"quote-content"},Ya={class:"message-text"},Wa={class:"message-input"},Ja={key:0,class:"image-preview-container"},Va=["src","alt"],Ga=["onClick"],Za={class:"input-row"},Qa={class:"input-actions"},Ea=["placeholder","disabled"],en=["disabled"],tn=100*1024*1024,Xe=50,mt="ChatImageCache",an=2,B="images",ie=50*1024*1024,vt=100,ue=500,Ye=2*1024*1024,gt=.8,nn=60*1e3,P=80,sn=Q({__name:"index",setup(E){function ee(e){try{return new URL(e).protocol==="file:"}catch{return false}}const te=Q({props:{src:{type:String,required:true},alt:{type:String,default:"头像"},channelKey:{type:String,required:true}},setup(e){const a=f("loading"),t=f(e.src),n=f(""),r=async()=>{try{a.value="loading";const o=await Re(e.channelKey,e.src);if(o){t.value=o,a.value="loaded";return}const l=new Image;l.crossOrigin="anonymous",l.referrerPolicy="no-referrer",l.draggable=false;const c=new Promise((p,g)=>{l.onload=()=>p(),l.onerror=()=>g(new Error("Direct load failed")),l.src=e.src}),v=new Promise((p,g)=>{setTimeout(()=>g(new Error("Timeout")),3e3)});try{await Promise.race([c,v]),t.value=e.src,a.value="loaded",le(e.channelKey,e.src).catch(p=>{console.warn("异步缓存头像失败:",p)})}catch{await s()}}catch(o){console.error("头像加载失败:",o),a.value="error",n.value="头像加载失败"}},s=async()=>{try{a.value="caching";const o=await le(e.channelKey,e.src);if(o)t.value=o,a.value="loaded";else throw new Error("缓存系统加载失败")}catch(o){console.error("缓存系统加载头像失败:",o),a.value="error",n.value=(o==null?void 0:o.message)||"缓存加载失败"}};return Pe(()=>{r()}),()=>{switch(a.value){case"loading":case"caching":return d("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase());case"loaded":return d("img",{src:t.value,alt:e.alt,draggable:false,style:{width:"100%",height:"100%","object-fit":"cover"}});case"error":return d("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase());default:return d("div",{class:"avatar-placeholder"},e.alt.charAt(0).toUpperCase())}}}}),de=Q({props:{src:{type:String,required:true},alt:{type:String,default:"图片"},filename:{type:String,default:""},channelKey:{type:String,required:true}},setup(e){const a=f("loading"),t=f(e.src),n=f(""),r=f(null),s=async()=>{try{a.value="loading";const l=await Re(e.channelKey,e.src);if(l){t.value=l,a.value="loaded";return}if(ee(e.src)){console.log("ImageComponent: 检测到本地文件,使用代理请求:",e.src),await o();return}const c=new Image;c.crossOrigin="anonymous",c.referrerPolicy="no-referrer",c.draggable=false;const v=new Promise((g,T)=>{c.onload=()=>g(),c.onerror=()=>T(new Error("Direct load failed")),c.src=e.src}),p=new Promise((g,T)=>{setTimeout(()=>T(new Error("Timeout")),3e3)});try{await Promise.race([v,p]),t.value=e.src,a.value="loaded",le(e.channelKey,e.src).catch(g=>{console.warn("异步缓存图片失败:",g)})}catch{await o()}}catch(l){console.error("图片加载失败:",l),a.value="error",n.value="图片加载失败"}},o=async()=>{try{a.value="caching";const l=await le(e.channelKey,e.src);if(l)t.value=l,a.value="loaded";else throw new Error("缓存系统加载失败")}catch(l){console.error("缓存系统加载图片失败:",l),a.value="error",n.value=(l==null?void 0:l.message)||"缓存加载失败"}};return Pe(()=>{s()}),()=>{switch(a.value){case"loading":return d("div",{class:"message-image-loading"},"加载中...");case"caching":return d("div",{class:"message-image-loading"},"[图片加载缓存中...]");case"loaded":return d("img",{src:t.value,alt:e.alt,class:"message-image",loading:"lazy",ref:r,draggable:false,style:{"max-width":"400px","max-height":"200px",width:"auto",height:"auto","object-fit":"contain"}});case"error":return d("div",{class:"message-image-error"},["图片加载失败",d("br"),d("small",e.filename||e.alt||"未知图片"),d("br"),d("small",{style:"color: #ff9800;"},n.value)]);default:return d("div",{class:"message-image-error"},"未知状态")}}}}),Se=Q({props:{data:{type:String,required:true},channelKey:{type:String,required:true}},setup(e){const t=(()=>{try{const r=JSON.parse(e.data);if(r.meta&&r.meta.detail_1){const s=r.meta.detail_1;return{type:"share_card",title:s.title||r.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:r}}catch(r){return console.error("解析JSON数据失败:",r),{type:"error",error:"无法解析的JSON数据"}}})(),n=()=>{t.type==="share_card"&&t.url&&window.open(t.url,"_blank","noopener,noreferrer")};return()=>t.type==="share_card"&&t.preview?d("img",{src:t.preview,alt:t.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:t.url?"pointer":"default"},title:t.url?`点击打开: ${t.title||"链接"}`:t.title,onError:r=>{const o=r.target.parentElement;o&&(o.style.display="none")}}):t.type==="error"?d("div",{class:"message-json-error"},[d("span",{class:"json-error-text"},t.error),d("details",{class:"json-raw-data"},[d("summary","查看原始数据"),d("pre",{class:"json-raw-content"},e.data)])]):d("div",{class:"message-json-raw"},[d("div",{class:"json-label"},"[JSON数据]"),d("details",{class:"json-raw-data"},[d("summary","查看详情"),d("pre",{class:"json-raw-content"},JSON.stringify(t.data,null,2))])])}}),pt=Q({props:{element:{type:Object,required:true},channelKey:{type:String,required:true}},setup(e){const a=f(false),t=()=>{a.value=!a.value},n=()=>{if(!e.element.children||e.element.children.length===0)return{previews:[],messageCount:0};const s=e.element.children.filter(c=>c.type==="message"),o=s.length;return{previews:s.slice(0,3).map(c=>{var g,T;const v=((g=c.attrs)==null?void 0:g.nickname)||"用户";let p="";if(c.children&&c.children.length>0){const $=c.children[0];$.type==="text"?(p=(((T=$.attrs)==null?void 0:T.content)||"").substring(0,20),p.length>15&&(p+="...")):$.type==="img"?p="[图片]":$.type==="video"?p="[视频]":p=`[${$.type}]`}return`${v}:${p}`}),messageCount:o}},r=(s,o)=>{var v,p,g;const l=((v=s.attrs)==null?void 0:v.nickname)||"用户",c=((p=s.attrs)==null?void 0:p.userId)||"unknown";return d("div",{key:o,class:"forwarded-message-item"},[d("div",{class:"forwarded-message-header"},[d("span",{class:"forwarded-message-nickname"},l),d("span",{class:"forwarded-message-userid"},`(${c})`)]),d("div",{class:"forwarded-message-content"},((g=s.children)==null?void 0:g.map((T,$)=>d(ye,{key:$,element:T,channelKey:e.channelKey})))||[])])};return()=>{var l;const{previews:s,messageCount:o}=n();return d("div",{class:"forward-message-container"},[d("div",{class:"forward-message-preview",onClick:t},[d("div",{class:"forward-message-title"},"聊天记录"),...s.map((c,v)=>d("div",{key:v,class:"forward-message-preview-item"},c)),d("div",{class:"forward-message-footer"},[d("span",{class:"forward-message-count"},`查看${o}条转发消息`),d("span",{class:"forward-message-toggle"},a.value?"▲":"▼")])]),a.value&&d("div",{class:"forward-message-expanded"},((l=e.element.children)==null?void 0:l.filter(c=>c.type==="message").map((c,v)=>r(c,v)))||[])])}}}),ye=Q({props:{element:{type:Object,required:true},channelKey:{type:String,required:true}},setup(e){const a=t=>{var n,r,s,o,l,c;switch(t.type){case"text":return d("span",{class:"message-text-content"},t.attrs.content||"");case"forward":return d("span",{class:"message-text-content"},`[转发消息 ${t.attrs.id}]`||"[转发消息]");case"img":case"image":const v=t.attrs.src||t.attrs.url||t.attrs.file;return d("div",{class:"message-image-container"},[d(de,{src:v,alt:t.attrs.summary||"图片",filename:t.attrs.filename||t.attrs.summary||"",channelKey:e.channelKey})]);case"mface":const p=t.attrs.src||t.attrs.url||t.attrs.file;return d("div",{class:"message-image-container"},[d(de,{src:p,alt:t.attrs.summary||"表情",filename:t.attrs.emojiId||t.attrs.summary||"",channelKey:e.channelKey})]);case"face":if((r=(n=t.children[0])==null?void 0:n.attrs)!=null&&r.src){const g=((o=(s=t.children[0])==null?void 0:s.attrs)==null?void 0:o.src)||((c=(l=t.children[0])==null?void 0:l.attrs)==null?void 0:c.url);return d("div",{class:"message-image-container"},[d(de,{src:g,alt:t.attrs.name||t.attrs.id||"[表情]",filename:t.attrs.name||t.attrs.id||"[表情]",channelKey:e.channelKey})])}else return d("span",{class:"message-text-content"},`[${t.attrs.name||t.attrs.id}]`||"[表情]");case"at":return d("span",{class:"message-at",title:t.attrs.name},`${t.attrs.name||t.attrs.id}`);case"json":return d("div",{class:"message-image-container"},[d(Se,{data:t.attrs.data||"",channelKey:e.channelKey})]);case"p":if(t.children&&t.children.length>0){const g=t.children.map((T,$)=>d(ye,{key:$,element:T,channelKey:e.channelKey}));return d("div",{class:"message-paragraph"},g)}else return d("div",{class:"message-paragraph"},"");case"figure":return d(pt,{element:t,channelKey:e.channelKey});default:return d("span",{class:"message-unknown",title:`未知消息类型: ${t.type}`},t.attrs.content||`[${t.type}]`)}};return()=>a(e.element)}}),u=f({bots:{},channels:{},messages:{}}),U=f({}),fe=f({maxMessagesPerChannel:1e3,keepMessagesOnClear:50,loggerinfo:false,blockedPlatforms:[],chatContainerHeight:80}),b=f({});let Be=0,w=null,K=0,M=0,We=0;const h=f(""),k=f(""),he=f("");function Je(e){return e.size||0}function pe(e){Be+=e,fe.value.loggerinfo&&console.log(`内存使用量变化: ${e>0?"+":""}${(e/1024/1024).toFixed(2)}MB, 总计: ${(Be/1024/1024).toFixed(2)}MB`)}function Ve(e=10){const a=Object.entries(b.value);if(a.length<=e)return;const t=a.slice(0,a.length-e);let n=0;t.forEach(([r,s])=>{URL.revokeObjectURL(s),delete b.value[r],n+=500*1024,fe.value.loggerinfo&&console.log("清理旧blob URL:",r)}),pe(-n)}function De(){Object.keys(b.value).length>Xe&&Ve(Math.floor(Xe*.7)),Be>tn&&Ve(Math.floor(Xe*.5))}const j=f([]),V=f(false),Te=f(),L=f(false),J=f("bots"),H=f(null),ae=f(null),Le=f(false),G=f({show:false,text:""}),D=f(),me=f(),qe=f(false),we=f(false),ne=f(false),F=f(""),A=f({x:0,y:0}),q=f({x:0,y:0}),Ge=f({x:0,y:0}),Ue=f({x:0,y:0}),Ke=f(0),N=f(null),se=f(false),I=f(null),x=f({show:false,x:0,y:0,type:null,targetId:"",isSecondClick:false}),X=f(new Set),Y=f(new Set),wt=R(()=>Object.values(u.value.bots).sort((a,t)=>{const n=X.value.has(a.selfId),r=X.value.has(t.selfId);return n&&!r?-1:!n&&r?1:0})),It=R(()=>!h.value||!u.value.channels[h.value]?[]:Object.values(u.value.channels[h.value]).sort((a,t)=>{const n=Y.value.has(`${h.value}:${a.id}`),r=Y.value.has(`${h.value}:${t.id}`);return n&&!r?-1:!n&&r?1:0})),Ze=R(()=>{if(!h.value||!k.value)return[];const e=`${h.value}:${k.value}`,a=u.value.messages[e]||[];return a.filter(t=>t.quote),a}),xt=R(()=>{var a;if(!h.value||!k.value)return"";const e=u.value.channels[h.value];return((a=e==null?void 0:e[k.value])==null?void 0:a.name)||""}),Ie=R(()=>!h.value||!k.value?"":`${h.value}:${k.value}`),Qe=R(()=>h.value&&k.value&&(he.value.trim()||j.value.length>0)&&!ne.value),Ct=R(()=>h.value&&k.value&&!ne.value),kt=R(()=>{if(!L.value)return"";switch(J.value){case"channels":return"show-channels";case"messages":return"show-messages";default:return""}}),bt=R(()=>L.value?"输入消息...(屏幕左滑返回)":"输入消息..."),_t=R(()=>{if(L.value){const e=fe.value.chatContainerHeight||80,a=100-e-19;return{height:`${e}vh`,marginTop:`${a}vh`}}return{}});function $t(e){h.value=e,k.value="",L.value&&(J.value="channels")}function St(e,a){if(e.preventDefault(),e.stopPropagation(),x.value.show&&x.value.type==="bot"&&x.value.targetId===a){O();return}Ee(e,"bot",a)}function Bt(e,a){if(e.preventDefault(),e.stopPropagation(),x.value.show&&x.value.type==="channel"&&x.value.targetId===a){O();return}Ee(e,"channel",a)}function Ee(e,a,t){let s=e.clientX,o=e.clientY;s+180>window.innerWidth&&(s=window.innerWidth-180-10),o+80>window.innerHeight&&(o=window.innerHeight-80-10),x.value={show:true,x:s,y:o,type:a,targetId:t,isSecondClick:false},document.addEventListener("click",O,{once:true}),document.addEventListener("keydown",et)}function O(){x.value.show=false,document.removeEventListener("click",O),document.removeEventListener("keydown",et)}function et(e){e.key==="Escape"&&x.value.show&&O()}async function Dt(e){X.value.has(e)?X.value.delete(e):X.value.add(e),await S("set-pinned-bots",{pinnedBots:Array.from(X.value)}),O()}async function Tt(e){const a=`${h.value}:${e}`;Y.value.has(a)?Y.value.delete(a):Y.value.add(a),await S("set-pinned-channels",{pinnedChannels:Array.from(Y.value)}),O()}async function Lt(e){try{const a=await S("delete-bot-data",{selfId:e});if(a.success){const t=Object.keys(u.value.messages).filter(n=>n.startsWith(`${e}:`));for(const n of t)delete u.value.messages[n],delete U.value[n],await $e(n);delete u.value.bots[e],delete u.value.channels[e],h.value===e&&(h.value="",k.value=""),_(a.message||"已删除该机器人的所有数据","success")}else throw new Error(a.error||"删除失败")}catch(a){console.error("删除机器人数据失败:",a),_("删除失败: "+((a==null?void 0:a.message)||String(a)),"error")}O()}async function qt(e){try{const a=await S("delete-channel-data",{selfId:h.value,channelId:e});if(a.success){const t=`${h.value}:${e}`;delete u.value.messages[t],delete U.value[t],u.value.channels[h.value]&&delete u.value.channels[h.value][e],await $e(t),k.value===e&&(k.value=""),_(a.message||"已删除该频道的所有数据","success")}else throw new Error(a.error||"删除失败")}catch(a){console.error("删除频道数据失败:",a),_("删除失败: "+((a==null?void 0:a.message)||String(a)),"error")}O()}async function Ut(e){k.value=e,we.value=false,L.value&&(J.value="messages"),h.value&&await aa(h.value,e),oe(()=>{re(),!L.value&&me.value&&me.value.focus()})}async function tt(){if(!Qe.value)return;const e=he.value.trim();if(!e&&j.value.length===0)return;ne.value=true;const a=[...j.value];try{const t=await S("send-message",{selfId:h.value,channelId:k.value,content:e,images:a.map(n=>({tempId:n.tempId,filename:n.filename}))});if(t.success){if(he.value="",a.forEach(n=>{URL.revokeObjectURL(n.preview)}),j.value=[],V.value=false,t.tempImageIds&&t.tempImageIds.length>0)try{await S("cleanup-temp-images",{tempImageIds:t.tempImageIds}),console.log("临时图片清理完成:",t.tempImageIds)}catch(n){console.warn("清理临时图片失败:",n)}}else console.error("消息发送失败:",t.error),_("发送失败: "+t.error,"error")}catch(t){console.error("发送消息时出错:",t),_("发送失败: "+((t==null?void 0:t.message)||String(t)),"error")}finally{ne.value=false}}function Kt(){V.value=!V.value}function jt(){Te.value&&Te.value.click(),V.value=false}async function At(e){const a=e.target,t=a.files;if(!(!t||t.length===0)){for(const n of Array.from(t))await at(n);a.value=""}}async function Nt(e){var t;const a=(t=e.clipboardData)==null?void 0:t.items;if(a){for(const n of Array.from(a))if(n.type.startsWith("image/")){e.preventDefault();const r=n.getAsFile();r&&await at(r)}}}async function at(e){try{if(e.size>10*1024*1024){_("图片文件过大,请选择小于10MB的图片","error");return}if(!e.type.startsWith("image/")){_("请选择图片文件","error");return}const a=await Rt(e),t=URL.createObjectURL(e),n=await S("upload-image",{file:a,filename:e.name,mimeType:e.type});n.success?j.value.push({tempId:n.tempId,filename:e.name,preview:t,size:e.size}):(URL.revokeObjectURL(t),_("图片上传失败: "+n.error,"error"))}catch(a){console.error("上传图片失败:",a),_("图片上传失败: "+((a==null?void 0:a.message)||String(a)),"error")}}async function Ot(e){try{const a=j.value.findIndex(t=>t.tempId===e);if(a!==-1){const t=j.value[a];URL.revokeObjectURL(t.preview),j.value.splice(a,1)}await S("delete-temp-image",{tempId:e})}catch(a){console.error("删除图片失败:",a)}}function Rt(e){return new Promise((a,t)=>{const n=new FileReader;n.onload=()=>a(n.result),n.onerror=t,n.readAsDataURL(e)})}function nt(e){const a=e.target;a.closest(".input-actions")||(V.value=false),a.closest(".context-menu")||O()}function st(e){return new Date(e).toLocaleTimeString("zh-CN",{hour:"2-digit",minute:"2-digit"})}function zt(e){if(typeof e=="number")switch(e){case 0:return"文本";case 1:return"私聊";default:return"未知"}return String(e)}function re(){D.value&&(D.value.scrollTop=D.value.scrollHeight,qe.value=false,we.value=false)}function xe(){if(D.value){const{scrollTop:e,scrollHeight:a,clientHeight:t}=D.value,r=a-(e+t)<=50,s=!r;qe.value=s,r?we.value=false:we.value=true}}function je(){if(!D.value)return true;const{scrollTop:e,scrollHeight:a,clientHeight:t}=D.value;return a-(e+t)<=200}function Ae(e){var n;if(!h.value)return 0;const a=`${h.value}:${e}`,t=U.value[a];return t!==void 0?t:((n=u.value.messages[a])==null?void 0:n.length)||0}function rt(e,a){e.preventDefault(),e.stopPropagation();const t="touches"in e?e.touches[0].clientX:e.clientX,n="touches"in e?e.touches[0].clientY:e.clientY;Ke.value=Date.now(),A.value={x:t,y:n},q.value={x:t,y:n},se.value=false;const s=e.target.getBoundingClientRect();Ge.value={x:s.left,y:s.top},Ue.value={x:t-s.left,y:n-s.top},N.value=window.setTimeout(()=>{if(Ke.value>0){se.value=true,F.value=a;const o=e.target,l=o.cloneNode(true);l.classList.add("dragging-clone"),l.style.position="fixed",l.style.zIndex="1000",l.style.pointerEvents="none";const c=o.getBoundingClientRect();l.style.left=`${c.left}px`,l.style.top=`${c.top}px`,l.style.width=`${c.width}px`,l.style.height=`${c.height}px`,document.body.appendChild(l),I.value=l,document.body.style.userSelect="none",document.body.style.cursor="grabbing",document.body.classList.add("dragging-bubble-global"),Ht(A.value.x,A.value.y)}},60),document.addEventListener("mousemove",Ce),document.addEventListener("mouseup",ke),document.addEventListener("touchmove",Ce),document.addEventListener("touchend",ke)}function Ce(e){if(!se.value||!I.value)return;e.preventDefault();const a="touches"in e?e.touches[0].clientX:e.clientX,t="touches"in e?e.touches[0].clientY:e.clientY;q.value={x:a,y:t};const n=q.value.x-A.value.x,r=q.value.y-A.value.y,s=Math.sqrt(n*n+r*r),o=Math.max(.3,1-s/(P*2)),l=Math.max(.8,1-s/(P*3)),c=s>P,v=q.value.x-Ue.value.x,p=q.value.y-Ue.value.y;I.value.style.left=`${v}px`,I.value.style.top=`${p}px`,I.value.style.transform=`scale(${l})`,I.value.style.opacity=`${o}`,I.value.style.backgroundColor=c?"#f44336":"#2196f3",I.value.style.boxShadow=c?"0 4px 12px rgba(244, 67, 54, 0.4)":"0 4px 12px rgba(33, 150, 243, 0.4)",c?I.value.classList.add("will-delete"):I.value.classList.remove("will-delete")}function ke(e){if(N.value&&(clearTimeout(N.value),N.value=null),N.value&&(clearTimeout(N.value),N.value=null),!se.value||!F.value){be();return}const a=F.value;if(Math.sqrt(Math.pow(q.value.x-A.value.x,2)+Math.pow(q.value.y-A.value.y,2))>P)Mt(a),be();else if(I.value){I.value.style.transition="all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)";const n=document.querySelector(`[data-channel-id="${a}"] .channel-message-count`);if(n){const r=n.getBoundingClientRect();I.value.style.left=`${r.left}px`,I.value.style.top=`${r.top}px`,I.value.style.transform="scale(1)",I.value.style.opacity="1",I.value.style.backgroundColor="#2196f3",I.value.style.boxShadow="0 4px 12px rgba(33, 150, 243, 0.4)"}setTimeout(()=>{be()},300)}else be()}function be(){N.value&&(clearTimeout(N.value),N.value=null),F.value="",A.value={x:0,y:0},q.value={x:0,y:0},Ge.value={x:0,y:0},Ke.value=0,se.value=false,document.removeEventListener("mousemove",Ce),document.removeEventListener("mouseup",ke),document.removeEventListener("touchmove",Ce),document.removeEventListener("touchend",ke),document.body.style.userSelect="",document.body.style.cursor="",document.body.classList.remove("dragging-bubble-global"),I.value&&I.value.parentNode&&(I.value.parentNode.removeChild(I.value),I.value=null),Ft()}function Pt(e){return F.value===e&&se.value?{visibility:"hidden",pointerEvents:"none",transition:"none"}:{}}function lt(e){if(F.value!==e)return 0;const a=q.value.x-A.value.x,t=q.value.y-A.value.y;return Math.sqrt(a*a+t*t)}async function Mt(e){if(h.value)try{const a=`${h.value}:${e}`,t=Ae(e),n=fe.value.keepMessagesOnClear;if(n>0&&t<=n){_("当前消息还很少诶~ 无需清理","success");return}const r=await S("clear-channel-history",{selfId:h.value,channelId:e});if(r.success)if(r.clearedCount&&r.clearedCount>0){if(u.value.messages[a]){const o=[...u.value.messages[a]].sort((l,c)=>l.timestamp-c.timestamp);u.value.messages[a]=o.slice(-r.keptCount)}U.value[a]=r.keptCount,await $e(a),_(`历史记录已清理,清理了 ${r.clearedCount} 条消息,保留最新 ${r.keptCount} 条`,"success")}else n===0?(u.value.messages[a]&&(u.value.messages[a]=[]),U.value[a]=0,await $e(a),_("历史记录已清理,所有消息已删除","success")):_("当前消息还很少诶~ 无需清理","success");else console.error("清理历史记录失败:",r.error),_("清理失败: "+r.error,"error")}catch(a){console.error("清理历史记录时出错:",a),_("清理失败: "+((a==null?void 0:a.message)||String(a)),"error")}}function _(e,a="success"){const t=document.createElement("div");t.className=`notification ${a}`,t.textContent=e;let n="#4caf50";switch(a){case"info":n="#2196f3";break;case"warn":n="#ff9800";break;case"error":n="#f44336";break;case"success":n="#4caf50";break}t.style.cssText=`
2
2
  position: fixed;
3
3
  top: 20px;
4
4
  right: 20px;
@@ -10,7 +10,7 @@ import{defineComponent as Q,ref as f,onMounted as Ne,h as d,computed as O,watch
10
10
  animation: slideIn 0.3s ease-out;
11
11
  background: ${n};
12
12
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
13
- `;const l=document.createElement("style");l.textContent=`
13
+ `;const r=document.createElement("style");r.textContent=`
14
14
  @keyframes slideIn {
15
15
  from { transform: translateX(100%); opacity: 0; }
16
16
  to { transform: translateX(0); opacity: 1; }
@@ -19,9 +19,9 @@ import{defineComponent as Q,ref as f,onMounted as Ne,h as d,computed as O,watch
19
19
  from { transform: translateX(0); opacity: 1; }
20
20
  to { transform: translateX(100%); opacity: 0; }
21
21
  }
22
- `,document.head.appendChild(l),document.body.appendChild(t),setTimeout(()=>{t.style.animation="slideOut 0.3s ease-in",setTimeout(()=>{t.parentNode&&t.parentNode.removeChild(t),l.parentNode&&l.parentNode.removeChild(l)},300)},3e3)}function Ut(e,a){const t=document.createElement("div");t.className="drag-threshold-circle",t.style.cssText=`
23
- left: ${e-A}px;
24
- top: ${a-A}px;
25
- width: ${A*2}px;
26
- height: ${A*2}px;
27
- `,document.body.appendChild(t),window.dragThresholdCircle=t}function jt(){const e=window.dragThresholdCircle;e&&e.parentNode&&(e.parentNode.removeChild(e),window.dragThresholdCircle=null)}async function Kt(){return new Promise((e,a)=>{const t=indexedDB.open(Fa,Ya);t.onerror=()=>{console.error("IndexedDB初始化失败:",t.error),e(false)},t.onsuccess=()=>{S=t.result,e(true)},t.onupgradeneeded=n=>{const l=n.target.result;if(!l.objectStoreNames.contains(R)){const s=l.createObjectStore(R,{keyPath:"url"});s.createIndex("channelKey","channelKey",{unique:false}),s.createIndex("timestamp","timestamp",{unique:false})}}})}async function Nt(e){return S?new Promise((a,t)=>{const s=S.transaction([R],"readonly").objectStore(R).get(e);s.onsuccess=()=>{a(s.result||null)},s.onerror=()=>{console.error("从IndexedDB获取图片失败:",s.error),a(null)}}):null}async function et(e){return S?new Promise(a=>{const l=S.transaction([R],"readwrite").objectStore(R).put(e);l.onsuccess=()=>{a(true)},l.onerror=()=>{console.error("保存图片到IndexedDB失败:",l.error),a(false)}}):false}async function tt(e){return S?new Promise(a=>{const l=S.transaction([R],"readwrite").objectStore(R).delete(e);l.onsuccess=()=>{a(true)},l.onerror=()=>{console.error("从IndexedDB删除图片失败:",l.error),a(false)}}):false}async function at(e){return S?new Promise(a=>{const s=S.transaction([R],"readonly").objectStore(R).index("channelKey").getAll(e);s.onsuccess=()=>{a(s.result||[])},s.onerror=()=>{console.error("获取频道图片失败:",s.error),a([])}}):[]}async function je(e,a){const t=b.value[a];if(t)return t;const n=await Nt(a);if(!n)return null;$e();const l=URL.createObjectURL(n.blob);return b.value[a]=l,ge(Me(n.blob)),n.timestamp=Date.now(),await et(n),l}async function se(e,a){try{const t=await je(e,a);if(t)return t;const n=await _("fetch-image",{url:a});if(!n.success)return console.error("获取图片失败:",n.error),null;const l=n.base64,s=n.contentType||"image/jpeg",o=atob(l),r=new Array(o.length);for(let fe=0;fe<o.length;fe++)r[fe]=o.charCodeAt(fe);const i=new Uint8Array(r),h=new Blob([i],{type:s}),g=await at(e);if(g.length>=rt){const Jt=g.sort((le,Vt)=>le.timestamp-Vt.timestamp).slice(0,g.length-rt+1);for(const le of Jt)await tt(le.url),b.value[le.url]&&(URL.revokeObjectURL(b.value[le.url]),delete b.value[le.url])}const y={url:a,blob:h,timestamp:Date.now(),size:h.size,channelKey:e};if(!await et(y))return console.error("保存图片到IndexedDB失败"),null;$e();const B=URL.createObjectURL(h);return b.value[a]=B,ge(Me(h)),B}catch(t){return console.error("缓存图片失败:",t),null}}async function ke(e){try{const a=await at(e);let t=0;for(const n of a)await tt(n.url),b.value[n.url]&&(URL.revokeObjectURL(b.value[n.url]),delete b.value[n.url],t+=n.size||0);t>0&&ge(-t)}catch(a){console.error("清理频道图片缓存失败:",a)}}function Ot(e){var a,t,n,l;if(!u.value.bots[e.selfId])u.value.bots[e.selfId]={selfId:e.selfId,platform:e.platform,username:((a=e.bot)==null?void 0:a.name)||`Bot-${e.selfId}`,avatar:(t=e.bot)==null?void 0:t.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),(l=e.bot)!=null&&l.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(r=>r.id===e.messageId)){const r={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},i=u.value.messages[s];let h=i.length;for(let y=i.length-1;y>=0;y--){if(i[y].timestamp<=e.timestamp){h=y+1;break}y===0&&(h=0)}i.splice(h,0,r),i.length>100&&(u.value.messages[s]=i.slice(-100)),D.value[s]=i.length;const g=De();re(()=>{setTimeout(()=>{g&&ne()},10)})}}if(e.elements&&e.elements.length>0){const s=`${e.selfId}:${e.channelId}`;e.elements.forEach(o=>{if((o.type==="img"||o.type==="image"||o.type==="mface")&&o.attrs){const r=o.attrs.src||o.attrs.url||o.attrs.file;r&&se(s,r).catch(i=>{console.warn("预缓存图片失败:",r,i)})}})}u.value={...u.value}}function Pt(e){const a=`${e.selfId}:${e.channelId}`;if(u.value.messages[a]||(u.value.messages[a]=[]),!u.value.messages[a].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},l=u.value.messages[a];let s=l.length;for(let r=l.length-1;r>=0;r--){if(l[r].timestamp<=e.timestamp){s=r+1;break}r===0&&(s=0)}l.splice(s,0,n),l.length>100&&(u.value.messages[a]=l.slice(-100)),D.value[a]=l.length;const o=De();re(()=>{setTimeout(()=>{o&&ne()},10)})}u.value={...u.value}}function Rt(e){var a,t,n,l;if(!u.value.bots[e.selfId])u.value.bots[e.selfId]={selfId:e.selfId,platform:e.platform,username:((a=e.bot)==null?void 0:a.name)||`Bot-${e.selfId}`,avatar:(t=e.bot)==null?void 0:t.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),(l=e.bot)!=null&&l.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(r=>r.id===e.messageId)){const r={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},i=u.value.messages[s];let h=i.length;for(let y=i.length-1;y>=0;y--){if(i[y].timestamp<=e.timestamp){h=y+1;break}y===0&&(h=0)}i.splice(h,0,r),i.length>100&&(u.value.messages[s]=i.slice(-100)),D.value[s]=i.length;const g=De();re(()=>{setTimeout(()=>{g&&ne()},10)})}}if(e.elements&&e.elements.length>0){const s=`${e.selfId}:${e.channelId}`;e.elements.forEach(o=>{if((o.type==="img"||o.type==="image"||o.type==="mface")&&o.attrs){const r=o.attrs.src||o.attrs.url||o.attrs.file;r&&se(s,r).catch(i=>{console.warn("预缓存图片失败:",r,i)})}})}u.value={...u.value}}nt(He,(e,a)=>{a.length===0&&e.length>0&&re(()=>{ne()})});async function At(){try{const e=await _("get-chat-data");if(e.success&&e.data){const a={};X.value=new Set(e.data.pinnedBots||[]),H.value=new Set(e.data.pinnedChannels||[]);for(const[t,n]of Object.entries(e.data.messages||{})){const l=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}));l.sort((s,o)=>s.timestamp-o.timestamp),a[t]=l}return u.value={bots:e.data.bots||{},channels:e.data.channels||{},messages:a},await Mt(),true}else return console.warn("获取聊天数据失败:",e.error),false}catch(e){return console.error("获取聊天数据时出错:",e),false}}async function Mt(){try{const e=await _("get-all-channel-message-counts");if(e.success&&e.counts){const a={};for(const[t,n]of Object.entries(e.counts))a[t]=n;D.value=a}else console.warn("获取频道消息数量失败:",e.error)}catch(e){console.error("获取频道消息数量时出错:",e)}}async function zt(){try{const e=await _("get-plugin-config");e.success&&e.config?ie.value=e.config:console.warn("获取插件配置失败:",e.error)}catch(e){console.error("获取插件配置时出错:",e)}}async function Xt(e,a){try{const t=await _("get-history-messages",{selfId:e,channelId:a});if(t.success&&t.messages){const n=`${e}:${a}`,l=t.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 l.sort((s,o)=>s.timestamp-o.timestamp),u.value.messages[n]=l,D.value[n]=l.length,u.value={...u.value},true}else return console.warn("获取历史消息失败:",t.error),false}catch(t){return console.error("获取历史消息时出错:",t),false}}function Ht(e){if(!L.value||e.touches.length!==1)return;const a=e.touches[0];M.value={x:a.clientX,y:a.clientY,time:Date.now()},ee.value={x:a.clientX,y:a.clientY},Be.value=false}function Ft(e){if(!L.value||!M.value||e.touches.length!==1)return;const a=e.touches[0];ee.value={x:a.clientX,y:a.clientY};const t=a.clientX-M.value.x,n=a.clientY-M.value.y;if(Math.abs(t)>Math.abs(n)&&Math.abs(t)>30){const l=t>0,s=W.value==="messages"||W.value==="channels";if(l&&s){Be.value=true;const o=Math.min(t,200),r=150;o>r?V.value={show:true,text:"松开返回"}:V.value={show:true,text:`滑动返回 ${Math.round(o/r*100)}%`},e.preventDefault()}else V.value={show:false,text:""}}else V.value={show:false,text:""}}function Yt(e){if(!L.value||!M.value)return;const t=Date.now()-M.value.time;if(ee.value){const n=ee.value.x-M.value.x,l=ee.value.y-M.value.y,s=n>150,o=Math.abs(n)>Math.abs(l),r=t<300&&n>80;(s&&o||r)&&Wt()}M.value=null,ee.value=null,Be.value=false,V.value={show:false,text:""}}function Wt(){switch(W.value){case"messages":W.value="channels";break;case"channels":W.value="bots",m.value="",C.value="";break}}function Ke(){L.value=window.innerWidth<=768}return Ne(async()=>{Ke(),window.addEventListener("resize",Ke),document.addEventListener("click",Ge),await Kt()||console.warn("IndexedDB初始化失败,图片缓存功能将不可用"),await zt(),await At();const a=Re("chat-message-event",Ot),t=Re("bot-message-sent-event",Pt),n=Re("chat-bot-message-event",Rt);nt(C,l=>{l&&re(()=>{$.value&&($.value.removeEventListener("scroll",we),$.value.addEventListener("scroll",we),we()),!L.value&&de.value&&de.value.focus()})},{immediate:true}),setInterval(()=>{$e()},2*60*1e3),Gt(()=>{window.removeEventListener("resize",Ke),document.removeEventListener("click",Ge),a&&typeof a=="function"&&a(),t&&typeof t=="function"&&t(),n&&typeof n=="function"&&n(),$.value&&$.value.removeEventListener("scroll",we),Object.values(b.value).forEach(l=>{URL.revokeObjectURL(l)}),b.value={},S&&(S.close(),S=null)})}),(e,a)=>(v(),p("div",{class:F(["chat-container",ht.value]),style:Oe(vt.value),onTouchstart:Ht,onTouchmove:Ft,onTouchend:Yt},[c("div",aa,[a[7]||(a[7]=c("div",{class:"panel-header"},[c("h3",null,"机器人")],-1)),c("div",na,[(v(true),p(P,null,oe(it.value,t=>(v(),p("div",{key:t.selfId,class:F(["bot-item",{active:m.value===t.selfId,pinned:X.value.has(t.selfId)}]),onClick:n=>gt(t.selfId),onContextmenu:n=>yt(n,t.selfId)},[c("div",la,[t.avatar?(v(),he(me(E),{key:0,src:t.avatar,alt:t.username,"channel-key":"bot-list"},null,8,["src","alt"])):(v(),p("div",ra,x(t.username.charAt(0).toUpperCase()),1))]),c("div",oa,[c("div",ca,x(t.username),1),c("div",ia,x(t.platform),1)]),c("div",{class:F(["bot-status",t.status])},null,2)],42,sa))),128))])]),c("div",ua,[a[8]||(a[8]=c("div",{class:"panel-header"},[c("h3",null,"频道")],-1)),m.value?(v(),p("div",fa,[(v(true),p(P,null,oe(ut.value,t=>(v(),p("div",{key:t.id,class:F(["channel-item",{active:C.value===t.id,pinned:H.value.has(`${m.value}:${t.id}`)}]),"data-channel-id":t.id,onClick:n=>kt(t.id),onContextmenu:n=>pt(n,t.id)},[c("div",ma,[c("div",va,x(t.name),1),c("div",ga,x(Tt(t.type)),1)]),Ue(t.id)>0?(v(),p("div",{key:0,class:F(["channel-message-count draggable-bubble",{dragging:z.value===t.id,"will-delete":z.value===t.id&&Ee(t.id)>A}]),onMousedown:n=>Ze(n,t.id),onTouchstart:n=>Ze(n,t.id),style:Oe(qt(t.id)),title:z.value===t.id?Ee(t.id)>A?"松开清理历史记录":"拖拽更远以清理历史记录":"拖拽清理历史记录"},x(Ue(t.id)),47,ya)):G("",true)],42,ha))),128))])):(v(),p("div",da," 请选择一个机器人 "))]),c("div",pa,[c("div",wa,[c("h3",null,x(dt.value||"选择频道"),1)]),!m.value||!C.value?(v(),p("div",Ia," 请选择机器人和频道 ")):(v(),p("div",xa,[c("div",{class:"message-history",ref_key:"messageHistory",ref:$},[(v(true),p(P,null,oe(He.value,t=>(v(),p("div",{key:t.id,class:F(["message-item",{"bot-message":t.isBot}])},[c("div",Ca,[t.avatar?(v(),he(me(E),{key:0,src:t.avatar,alt:t.username,"channel-key":pe.value},null,8,["src","alt","channel-key"])):(v(),p("div",ka,x(t.username.charAt(0).toUpperCase()),1))]),c("div",ba,[c("div",_a,[c("span",$a,x(t.username),1),c("span",Sa,x(Qe(t.timestamp)),1)]),t.quote?(v(),p("div",Ba,[c("div",La,[c("div",Ta,[t.quote.user.avatar?(v(),he(me(E),{key:0,src:t.quote.user.avatar,alt:t.quote.user.username,"channel-key":pe.value},null,8,["src","alt","channel-key"])):(v(),p("div",qa,x(t.quote.user.username.charAt(0).toUpperCase()),1))]),c("span",Da,x(t.quote.user.username),1),c("span",Ua,x(Qe(t.quote.timestamp)),1)]),c("div",ja,[t.quote.elements&&t.quote.elements.length>0?(v(true),p(P,{key:0},oe(t.quote.elements,(n,l)=>(v(),he(me(ve),{key:`quote-${l}`,element:n,"channel-key":pe.value},null,8,["element","channel-key"]))),128)):(v(),p(P,{key:1},[Pe(x(t.quote.content),1)],64))])])):G("",true),c("div",Ka,[t.elements&&t.elements.length>0?(v(true),p(P,{key:0},oe(t.elements,(n,l)=>(v(),he(me(ve),{key:l,element:n,"channel-key":pe.value},null,8,["element","channel-key"]))),128)):(v(),p(P,{key:1},[Pe(x(t.content),1)],64))])])],2))),128))],512),st(c("div",{class:"floating-scroll-button",onClick:ne},a[9]||(a[9]=[c("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},[c("path",{d:"M7 10l5 5 5-5z"})],-1)]),512),[[Qt,Le.value]]),c("div",Na,[U.value.length>0?(v(),p("div",Oa,[(v(true),p(P,null,oe(U.value,t=>(v(),p("div",{key:t.tempId,class:"image-preview-item"},[c("img",{src:t.preview,alt:t.filename,class:"preview-image"},null,8,Pa),c("button",{class:"remove-image-btn",onClick:n=>Bt(t.tempId),title:"删除图片"},a[10]||(a[10]=[c("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"currentColor"},[c("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,Ra)]))),128))])):G("",true),c("div",Aa,[c("div",Ma,[c("button",{class:F(["add-button",{active:J.value}]),onClick:bt,title:"更多操作"},a[11]||(a[11]=[c("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2.5","stroke-linecap":"round","stroke-linejoin":"round"},[c("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),c("line",{x1:"5",y1:"12",x2:"19",y2:"12"})],-1)]),2),J.value?(v(),p("div",{key:0,class:"action-menu",onClick:a[0]||(a[0]=lt(()=>{},["stop"]))},[c("button",{class:"action-menu-item",onClick:_t},a[12]||(a[12]=[c("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[c("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),c("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),c("polyline",{points:"21,15 16,10 5,21"})],-1),Pe(" 上传图片 ",-1)]))])):G("",true)]),st(c("input",{"onUpdate:modelValue":a[1]||(a[1]=t=>ue.value=t),type:"text",placeholder:mt.value,onKeyup:Zt(Je,["enter"]),disabled:!ft.value,ref_key:"messageInput",ref:de,onPaste:St},null,40,za),[[Et,ue.value]]),c("button",{onClick:Je,disabled:!Fe.value,class:F({"is-sending":te.value})},x(te.value?"发送中...":"发送"),11,Xa)]),c("input",{type:"file",ref_key:"fileInput",ref:Se,onChange:$t,accept:"image/*",multiple:"",style:{display:"none"}},null,544)])]))]),I.value.show?(v(),p("div",{key:0,class:"context-menu",style:Oe({left:I.value.x+"px",top:I.value.y+"px"}),onClick:a[6]||(a[6]=lt(()=>{},["stop"]))},[I.value.type==="bot"?(v(),p(P,{key:0},[c("div",{class:"context-menu-item",onClick:a[2]||(a[2]=t=>wt(I.value.targetId))},x(X.value.has(I.value.targetId)?"取消置顶":"置顶"),1),c("div",{class:"context-menu-item danger",onClick:a[3]||(a[3]=t=>xt(I.value.targetId))}," 彻底删除此机器人所有数据 ")],64)):G("",true),I.value.type==="channel"?(v(),p(P,{key:1},[c("div",{class:"context-menu-item",onClick:a[4]||(a[4]=t=>It(I.value.targetId))},x(H.value.has(`${m.value}:${I.value.targetId}`)?"取消置顶":"置顶"),1),c("div",{class:"context-menu-item danger",onClick:a[5]||(a[5]=t=>Ct(I.value.targetId))}," 彻底删除此频道所有数据 ")],64)):G("",true)],4)):G("",true),c("div",{class:F(["swipe-indicator",{show:V.value.show}])},x(V.value.text),3)],38))}}),ot=(Z,Y)=>{const E=Z.__vccOpts||Z;for(const[ce,be]of Y)E[ce]=be;return E},Ja=ot(Wa,[["__scopeId","data-v-fc970c70"]]),Va={},Ga={class:"k-icon",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none"};function Qa(Z,Y){return v(),p("svg",Ga,Y[0]||(Y[0]=[c("path",{d:"M8 10.5H16",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),c("path",{d:"M8 14H13.5",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),c("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 Za=ot(Va,[["render",Qa]]);ta.register("activity:chat",Za);const tn=Z=>{Z.page({name:"聊天室",path:"/chat-patch",desc:"",authority:4,icon:"activity:chat",component:Q({setup(){return()=>d(ea("k-layout"),{},{default:()=>d(Ja)})}})})};export{tn as default};
22
+ `,document.head.appendChild(r),document.body.appendChild(t),setTimeout(()=>{t.style.animation="slideOut 0.3s ease-in",setTimeout(()=>{t.parentNode&&t.parentNode.removeChild(t),r.parentNode&&r.parentNode.removeChild(r)},300)},3e3)}function Ht(e,a){const t=document.createElement("div");t.className="drag-threshold-circle",t.style.cssText=`
23
+ left: ${e-P}px;
24
+ top: ${a-P}px;
25
+ width: ${P*2}px;
26
+ height: ${P*2}px;
27
+ `,document.body.appendChild(t),window.dragThresholdCircle=t}function Ft(){const e=window.dragThresholdCircle;e&&e.parentNode&&(e.parentNode.removeChild(e),window.dragThresholdCircle=null)}async function Ne(){try{if(!w)return false;const e=Date.now();if(e-We<nn)return true;We=e;const a=await ot();K=a.totalSize,M=a.totalImages,console.log("数据库健康检查:",{大小:`${(K/1024/1024).toFixed(2)}MB / ${(ie/1024/1024).toFixed(2)}MB`,图片数量:`${M} / ${ue}`,使用率:`${(K/ie*100).toFixed(1)}%`});const t=K/ie,n=M/ue;return(t>gt||n>gt)&&(console.warn("数据库使用率过高,开始自动清理"),await _e()),(t>.95||n>.95)&&(console.error("数据库接近极限,执行紧急清理"),await Xt()),true}catch(e){return console.error("数据库健康检查失败:",e),false}}async function ot(){return w?new Promise(e=>{const n=w.transaction([B],"readonly").objectStore(B).getAll();n.onsuccess=()=>{const r=n.result||[];let s=0;const o={};r.forEach(l=>{s+=l.size||0,o[l.channelKey]=(o[l.channelKey]||0)+1}),e({totalSize:s,totalImages:r.length,channelStats:o})},n.onerror=()=>{console.error("获取数据库统计失败:",n.error),e({totalSize:0,totalImages:0,channelStats:{}})}}):{totalSize:0,totalImages:0,channelStats:{}}}async function _e(){try{console.log("开始自动清理...");const e=await ct();if(e.length===0)return;const a={};e.forEach(r=>{a[r.channelKey]||(a[r.channelKey]=[]),a[r.channelKey].push(r)});let t=0,n=0;for(const[r,s]of Object.entries(a))if(s.length>vt){s.sort((l,c)=>l.timestamp-c.timestamp);const o=s.slice(0,s.length-vt);for(const l of o)await Oe(l.url),t++,n+=l.size||0,b.value[l.url]&&(URL.revokeObjectURL(b.value[l.url]),delete b.value[l.url])}console.log(`自动清理完成: 清理了 ${t} 张图片,释放了 ${(n/1024/1024).toFixed(2)}MB`),M-=t,K-=n}catch(e){console.error("自动清理失败:",e)}}async function Xt(){try{console.log("开始紧急清理...");const e=await ct();if(e.length===0)return;e.sort((s,o)=>o.timestamp-s.timestamp);const a=Math.floor(ue*.3),t=e.slice(a);let n=0,r=0;for(const s of t)await Oe(s.url),n++,r+=s.size||0,b.value[s.url]&&(URL.revokeObjectURL(b.value[s.url]),delete b.value[s.url]);console.log(`紧急清理完成: 清理了 ${n} 张图片,释放了 ${(r/1024/1024).toFixed(2)}MB`),M=a,K-=r}catch(e){console.error("紧急清理失败:",e)}}async function ct(){return w?new Promise(e=>{const n=w.transaction([B],"readonly").objectStore(B).getAll();n.onsuccess=()=>{e(n.result||[])},n.onerror=()=>{console.error("获取所有图片失败:",n.error),e([])}}):[]}async function Yt(){return new Promise(e=>{try{w&&(w.close(),w=null);const a=indexedDB.deleteDatabase(mt);a.onsuccess=()=>{console.log("IndexedDB数据库已完全清理"),K=0,M=0,e(true)},a.onerror=()=>{console.error("清理IndexedDB数据库失败:",a.error),e(false)},a.onblocked=()=>{console.warn("IndexedDB数据库删除被阻塞,可能有其他连接正在使用"),setTimeout(()=>{e(false)},5e3)}}catch(a){console.error("清理数据库时出错:",a),e(false)}})}async function Wt(){try{return await it()?(setTimeout(async()=>{const a=await ot();console.log("数据库初始状态:",{大小:`${(a.totalSize/1024/1024).toFixed(2)}MB`,图片数量:a.totalImages,频道分布:a.channelStats}),(a.totalSize>ie*.9||a.totalImages>ue*.9)&&(console.warn("数据库初始状态接近限制,执行清理"),await _e())},1e3),true):(console.warn("数据库打开失败,尝试清理后重新初始化"),await Yt(),await it())}catch(e){return console.error("IndexedDB初始化出错:",e),false}}async function it(){return new Promise(e=>{try{const a=indexedDB.open(mt,an);a.onerror=()=>{console.error("IndexedDB打开失败:",a.error),e(false)},a.onsuccess=()=>{w=a.result,w.onerror=t=>{console.error("IndexedDB运行时错误:",t)},w.onversionchange=()=>{console.warn("IndexedDB版本变更,关闭连接"),w==null||w.close(),w=null},e(true)},a.onupgradeneeded=t=>{const n=t.target.result;if(!n.objectStoreNames.contains(B)){const r=n.createObjectStore(B,{keyPath:"url"});r.createIndex("channelKey","channelKey",{unique:false}),r.createIndex("timestamp","timestamp",{unique:false}),r.createIndex("size","size",{unique:false}),console.log("IndexedDB对象存储创建完成")}},a.onblocked=()=>{console.warn("IndexedDB打开被阻塞"),e(false)}}catch(a){console.error("打开数据库时出错:",a),e(false)}})}async function Jt(e){return w?new Promise((a,t)=>{const s=w.transaction([B],"readonly").objectStore(B).get(e);s.onsuccess=()=>{a(s.result||null)},s.onerror=()=>{console.error("从IndexedDB获取图片失败:",s.error),a(null)}}):null}async function ut(e){if(!w)return false;try{return e.size>Ye?(console.warn(`图片过大,跳过缓存: ${(e.size/1024/1024).toFixed(2)}MB > ${(Ye/1024/1024).toFixed(2)}MB`),false):(await Ne(),K+e.size>ie&&(console.warn("添加图片会超过数据库大小限制,执行清理"),await _e(),K+e.size>ie)?(console.warn("清理后仍会超过限制,跳过此图片"),false):M>=ue&&(console.warn("图片数量已达上限,执行清理"),await _e(),M>=ue)?(console.warn("清理后仍达上限,跳过此图片"),false):new Promise(a=>{const r=w.transaction([B],"readwrite").objectStore(B).put(e);r.onsuccess=()=>{K+=e.size,M+=1,a(true)},r.onerror=()=>{console.error("保存图片到IndexedDB失败:",r.error),a(false)}}))}catch(a){return console.error("保存图片时出错:",a),false}}async function Oe(e){return w?new Promise(a=>{const r=w.transaction([B],"readwrite").objectStore(B).delete(e);r.onsuccess=()=>{a(true)},r.onerror=()=>{console.error("从IndexedDB删除图片失败:",r.error),a(false)}}):false}async function Vt(e){return w?new Promise(a=>{const s=w.transaction([B],"readonly").objectStore(B).index("channelKey").getAll(e);s.onsuccess=()=>{a(s.result||[])},s.onerror=()=>{console.error("获取频道图片失败:",s.error),a([])}}):[]}async function Re(e,a){const t=b.value[a];if(t)return t;const n=await Jt(a);if(!n)return null;De();const r=URL.createObjectURL(n.blob);return b.value[a]=r,pe(Je(n.blob)),n.timestamp=Date.now(),await ut(n),r}async function le(e,a){try{const t=await Re(e,a);if(t)return t;const n=await S("fetch-image",{url:a});if(!n.success)return console.error("获取图片失败:",n.error),null;const r=n.base64,s=n.contentType||"image/jpeg",o=atob(r),l=new Array(o.length);for(let $=0;$<o.length;$++)l[$]=o.charCodeAt($);const c=new Uint8Array(l),v=new Blob([c],{type:s});if(v.size>Ye)return console.warn(`图片过大,跳过缓存: ${(v.size/1024/1024).toFixed(2)}MB`),null;const p={url:a,blob:v,timestamp:Date.now(),size:v.size,channelKey:e};if(!await ut(p))return console.error("保存图片到IndexedDB失败"),null;De();const T=URL.createObjectURL(v);return b.value[a]=T,pe(Je(v)),T}catch(t){return console.error("缓存图片失败:",t),null}}async function $e(e){try{const a=await Vt(e);let t=0;for(const n of a)await Oe(n.url),b.value[n.url]&&(URL.revokeObjectURL(b.value[n.url]),delete b.value[n.url],t+=n.size||0);t>0&&pe(-t)}catch(a){console.error("清理频道图片缓存失败:",a)}}function Gt(e){var a,t,n,r;if(!u.value.bots[e.selfId])u.value.bots[e.selfId]={selfId:e.selfId,platform:e.platform,username:((a=e.bot)==null?void 0:a.name)||`Bot-${e.selfId}`,avatar:(t=e.bot)==null?void 0:t.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),(r=e.bot)!=null&&r.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(l=>l.id===e.messageId)){const l={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},c=u.value.messages[s];let v=c.length;for(let g=c.length-1;g>=0;g--){if(c[g].timestamp<=e.timestamp){v=g+1;break}g===0&&(v=0)}c.splice(v,0,l),c.length>100&&(u.value.messages[s]=c.slice(-100)),U.value[s]=c.length;const p=je();oe(()=>{setTimeout(()=>{p&&re()},10)})}}if(e.elements&&e.elements.length>0){const s=`${e.selfId}:${e.channelId}`;e.elements.forEach(o=>{if((o.type==="img"||o.type==="image"||o.type==="mface")&&o.attrs){const l=o.attrs.src||o.attrs.url||o.attrs.file;l&&le(s,l).catch(c=>{console.warn("预缓存图片失败:",l,c)})}})}u.value={...u.value}}function Zt(e){const a=`${e.selfId}:${e.channelId}`;if(u.value.messages[a]||(u.value.messages[a]=[]),!u.value.messages[a].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},r=u.value.messages[a];let s=r.length;for(let l=r.length-1;l>=0;l--){if(r[l].timestamp<=e.timestamp){s=l+1;break}l===0&&(s=0)}r.splice(s,0,n),r.length>100&&(u.value.messages[a]=r.slice(-100)),U.value[a]=r.length;const o=je();oe(()=>{setTimeout(()=>{o&&re()},10)})}u.value={...u.value}}function Qt(e){var a,t,n,r;if(!u.value.bots[e.selfId])u.value.bots[e.selfId]={selfId:e.selfId,platform:e.platform,username:((a=e.bot)==null?void 0:a.name)||`Bot-${e.selfId}`,avatar:(t=e.bot)==null?void 0:t.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),(r=e.bot)!=null&&r.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(l=>l.id===e.messageId)){const l={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},c=u.value.messages[s];let v=c.length;for(let g=c.length-1;g>=0;g--){if(c[g].timestamp<=e.timestamp){v=g+1;break}g===0&&(v=0)}c.splice(v,0,l),c.length>100&&(u.value.messages[s]=c.slice(-100)),U.value[s]=c.length;const p=je();oe(()=>{setTimeout(()=>{p&&re()},10)})}}if(e.elements&&e.elements.length>0){const s=`${e.selfId}:${e.channelId}`;e.elements.forEach(o=>{if((o.type==="img"||o.type==="image"||o.type==="mface")&&o.attrs){const l=o.attrs.src||o.attrs.url||o.attrs.file;l&&le(s,l).catch(c=>{console.warn("预缓存图片失败:",l,c)})}})}u.value={...u.value}}dt(Ze,(e,a)=>{a.length===0&&e.length>0&&oe(()=>{re()})});async function Et(){try{const e=await S("get-chat-data");if(e.success&&e.data){const a={};X.value=new Set(e.data.pinnedBots||[]),Y.value=new Set(e.data.pinnedChannels||[]);for(const[t,n]of Object.entries(e.data.messages||{})){const r=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}));r.sort((s,o)=>s.timestamp-o.timestamp),a[t]=r}return u.value={bots:e.data.bots||{},channels:e.data.channels||{},messages:a},await ea(),true}else return console.warn("获取聊天数据失败:",e.error),false}catch(e){return console.error("获取聊天数据时出错:",e),false}}async function ea(){try{const e=await S("get-all-channel-message-counts");if(e.success&&e.counts){const a={};for(const[t,n]of Object.entries(e.counts))a[t]=n;U.value=a}else console.warn("获取频道消息数量失败:",e.error)}catch(e){console.error("获取频道消息数量时出错:",e)}}async function ta(){try{const e=await S("get-plugin-config");e.success&&e.config?fe.value=e.config:console.warn("获取插件配置失败:",e.error)}catch(e){console.error("获取插件配置时出错:",e)}}async function aa(e,a){try{const t=await S("get-history-messages",{selfId:e,channelId:a});if(t.success&&t.messages){const n=`${e}:${a}`,r=t.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 r.sort((s,o)=>s.timestamp-o.timestamp),u.value.messages[n]=r,U.value[n]=r.length,u.value={...u.value},true}else return console.warn("获取历史消息失败:",t.error),false}catch(t){return console.error("获取历史消息时出错:",t),false}}function na(e){if(!L.value||e.touches.length!==1)return;const a=e.touches[0];H.value={x:a.clientX,y:a.clientY,time:Date.now()},ae.value={x:a.clientX,y:a.clientY},Le.value=false}function sa(e){if(!L.value||!H.value||e.touches.length!==1)return;const a=e.touches[0];ae.value={x:a.clientX,y:a.clientY};const t=a.clientX-H.value.x,n=a.clientY-H.value.y;if(Math.abs(t)>Math.abs(n)&&Math.abs(t)>30){const r=t>0,s=J.value==="messages"||J.value==="channels";if(r&&s){Le.value=true;const o=Math.min(t,200),l=150;o>l?G.value={show:true,text:"松开返回"}:G.value={show:true,text:`滑动返回 ${Math.round(o/l*100)}%`},e.preventDefault()}else G.value={show:false,text:""}}else G.value={show:false,text:""}}function ra(e){if(!L.value||!H.value)return;const t=Date.now()-H.value.time;if(ae.value){const n=ae.value.x-H.value.x,r=ae.value.y-H.value.y,s=n>150,o=Math.abs(n)>Math.abs(r),l=t<300&&n>80;(s&&o||l)&&la()}H.value=null,ae.value=null,Le.value=false,G.value={show:false,text:""}}function la(){switch(J.value){case"messages":J.value="channels";break;case"channels":J.value="bots",h.value="",k.value="";break}}function ze(){L.value=window.innerWidth<=768}return Pe(async()=>{ze(),window.addEventListener("resize",ze),document.addEventListener("click",nt),await Wt()?(console.log("IndexedDB初始化成功"),setTimeout(async()=>{await Ne()},2e3),setInterval(async()=>{await Ne()},5*60*1e3)):console.warn("IndexedDB初始化失败,图片缓存功能将不可用"),await ta(),await Et();const a=Fe("chat-message-event",Gt),t=Fe("bot-message-sent-event",Zt),n=Fe("chat-bot-message-event",Qt);dt(k,r=>{r&&oe(()=>{D.value&&(D.value.removeEventListener("scroll",xe),D.value.addEventListener("scroll",xe),xe()),!L.value&&me.value&&me.value.focus()})},{immediate:true}),setInterval(()=>{De()},2*60*1e3),oa(()=>{window.removeEventListener("resize",ze),document.removeEventListener("click",nt),a&&typeof a=="function"&&a(),t&&typeof t=="function"&&t(),n&&typeof n=="function"&&n(),D.value&&D.value.removeEventListener("scroll",xe),Object.values(b.value).forEach(r=>{URL.revokeObjectURL(r)}),b.value={},w&&(w.close(),w=null)})}),(e,a)=>(m(),y("div",{class:W(["chat-container",kt.value]),style:Me(_t.value),onTouchstart:na,onTouchmove:sa,onTouchend:ra},[i("div",ha,[a[7]||(a[7]=i("div",{class:"panel-header"},[i("h3",null,"机器人")],-1)),i("div",ma,[(m(true),y(z,null,ce(wt.value,t=>(m(),y("div",{key:t.selfId,class:W(["bot-item",{active:h.value===t.selfId,pinned:X.value.has(t.selfId)}]),onClick:n=>$t(t.selfId),onContextmenu:n=>St(n,t.selfId)},[i("div",ga,[t.avatar?(m(),ve(ge(te),{key:0,src:t.avatar,alt:t.username,"channel-key":"bot-list"},null,8,["src","alt"])):(m(),y("div",ya,C(t.username.charAt(0).toUpperCase()),1))]),i("div",pa,[i("div",wa,C(t.username),1),i("div",Ia,C(t.platform),1)]),i("div",{class:W(["bot-status",t.status])},null,2)],42,va))),128))])]),i("div",xa,[a[8]||(a[8]=i("div",{class:"panel-header"},[i("h3",null,"频道")],-1)),h.value?(m(),y("div",ka,[(m(true),y(z,null,ce(It.value,t=>(m(),y("div",{key:t.id,class:W(["channel-item",{active:k.value===t.id,pinned:Y.value.has(`${h.value}:${t.id}`)}]),"data-channel-id":t.id,onClick:n=>Ut(t.id),onContextmenu:n=>Bt(n,t.id)},[i("div",_a,[i("div",$a,C(t.name),1),i("div",Sa,C(zt(t.type)),1)]),Ae(t.id)>0?(m(),y("div",{key:0,class:W(["channel-message-count draggable-bubble",{dragging:F.value===t.id,"will-delete":F.value===t.id&&lt(t.id)>P}]),onMousedown:n=>rt(n,t.id),onTouchstart:n=>rt(n,t.id),style:Me(Pt(t.id)),title:F.value===t.id?lt(t.id)>P?"松开清理历史记录":"拖拽更远以清理历史记录":"拖拽清理历史记录"},C(Ae(t.id)),47,Ba)):Z("",true)],42,ba))),128))])):(m(),y("div",Ca," 请选择一个机器人 "))]),i("div",Da,[i("div",Ta,[i("h3",null,C(xt.value||"选择频道"),1)]),!h.value||!k.value?(m(),y("div",La," 请选择机器人和频道 ")):(m(),y("div",qa,[i("div",{class:"message-history",ref_key:"messageHistory",ref:D},[(m(true),y(z,null,ce(Ze.value,t=>(m(),y("div",{key:t.id,class:W(["message-item",{"bot-message":t.isBot}])},[i("div",Ua,[t.avatar?(m(),ve(ge(te),{key:0,src:t.avatar,alt:t.username,"channel-key":Ie.value},null,8,["src","alt","channel-key"])):(m(),y("div",Ka,C(t.username.charAt(0).toUpperCase()),1))]),i("div",ja,[i("div",Aa,[i("span",Na,C(t.username),1),i("span",Oa,C(st(t.timestamp)),1)]),t.quote?(m(),y("div",Ra,[i("div",za,[i("div",Pa,[t.quote.user.avatar?(m(),ve(ge(te),{key:0,src:t.quote.user.avatar,alt:t.quote.user.username,"channel-key":Ie.value},null,8,["src","alt","channel-key"])):(m(),y("div",Ma,C(t.quote.user.username.charAt(0).toUpperCase()),1))]),i("span",Ha,C(t.quote.user.username),1),i("span",Fa,C(st(t.quote.timestamp)),1)]),i("div",Xa,[t.quote.elements&&t.quote.elements.length>0?(m(true),y(z,{key:0},ce(t.quote.elements,(n,r)=>(m(),ve(ge(ye),{key:`quote-${r}`,element:n,"channel-key":Ie.value},null,8,["element","channel-key"]))),128)):(m(),y(z,{key:1},[He(C(t.quote.content),1)],64))])])):Z("",true),i("div",Ya,[t.elements&&t.elements.length>0?(m(true),y(z,{key:0},ce(t.elements,(n,r)=>(m(),ve(ge(ye),{key:r,element:n,"channel-key":Ie.value},null,8,["element","channel-key"]))),128)):(m(),y(z,{key:1},[He(C(t.content),1)],64))])])],2))),128))],512),ft(i("div",{class:"floating-scroll-button",onClick:re},a[9]||(a[9]=[i("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"currentColor"},[i("path",{d:"M7 10l5 5 5-5z"})],-1)]),512),[[ca,qe.value]]),i("div",Wa,[j.value.length>0?(m(),y("div",Ja,[(m(true),y(z,null,ce(j.value,t=>(m(),y("div",{key:t.tempId,class:"image-preview-item"},[i("img",{src:t.preview,alt:t.filename,class:"preview-image"},null,8,Va),i("button",{class:"remove-image-btn",onClick:n=>Ot(t.tempId),title:"删除图片"},a[10]||(a[10]=[i("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"currentColor"},[i("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,Ga)]))),128))])):Z("",true),i("div",Za,[i("div",Qa,[i("button",{class:W(["add-button",{active:V.value}]),onClick:Kt,title:"更多操作"},a[11]||(a[11]=[i("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2.5","stroke-linecap":"round","stroke-linejoin":"round"},[i("line",{x1:"12",y1:"5",x2:"12",y2:"19"}),i("line",{x1:"5",y1:"12",x2:"19",y2:"12"})],-1)]),2),V.value?(m(),y("div",{key:0,class:"action-menu",onClick:a[0]||(a[0]=ht(()=>{},["stop"]))},[i("button",{class:"action-menu-item",onClick:jt},a[12]||(a[12]=[i("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[i("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),i("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),i("polyline",{points:"21,15 16,10 5,21"})],-1),He(" 上传图片 ",-1)]))])):Z("",true)]),ft(i("input",{"onUpdate:modelValue":a[1]||(a[1]=t=>he.value=t),type:"text",placeholder:bt.value,onKeyup:ia(tt,["enter"]),disabled:!Ct.value,ref_key:"messageInput",ref:me,onPaste:Nt},null,40,Ea),[[ua,he.value]]),i("button",{onClick:tt,disabled:!Qe.value,class:W({"is-sending":ne.value})},C(ne.value?"发送中...":"发送"),11,en)]),i("input",{type:"file",ref_key:"fileInput",ref:Te,onChange:At,accept:"image/*",multiple:"",style:{display:"none"}},null,544)])]))]),x.value.show?(m(),y("div",{key:0,class:"context-menu",style:Me({left:x.value.x+"px",top:x.value.y+"px"}),onClick:a[6]||(a[6]=ht(()=>{},["stop"]))},[x.value.type==="bot"?(m(),y(z,{key:0},[i("div",{class:"context-menu-item",onClick:a[2]||(a[2]=t=>Dt(x.value.targetId))},C(X.value.has(x.value.targetId)?"取消置顶":"置顶"),1),i("div",{class:"context-menu-item danger",onClick:a[3]||(a[3]=t=>Lt(x.value.targetId))}," 彻底删除此机器人所有数据 ")],64)):Z("",true),x.value.type==="channel"?(m(),y(z,{key:1},[i("div",{class:"context-menu-item",onClick:a[4]||(a[4]=t=>Tt(x.value.targetId))},C(Y.value.has(`${h.value}:${x.value.targetId}`)?"取消置顶":"置顶"),1),i("div",{class:"context-menu-item danger",onClick:a[5]||(a[5]=t=>qt(x.value.targetId))}," 彻底删除此频道所有数据 ")],64)):Z("",true)],4)):Z("",true),i("div",{class:W(["swipe-indicator",{show:G.value.show}])},C(G.value.text),3)],38))}}),yt=(E,ee)=>{const te=E.__vccOpts||E;for(const[de,Se]of ee)te[de]=Se;return te},rn=yt(sn,[["__scopeId","data-v-323dce07"]]),ln={},on={class:"k-icon",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none"};function cn(E,ee){return m(),y("svg",on,ee[0]||(ee[0]=[i("path",{d:"M8 10.5H16",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),i("path",{d:"M8 14H13.5",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"},null,-1),i("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 un=yt(ln,[["render",cn]]);fa.register("activity:chat",un);const hn=E=>{E.page({name:"聊天室",path:"/chat-patch",desc:"",authority:4,icon:"activity:chat",component:Q({setup(){return()=>d(da("k-layout"),{},{default:()=>d(rn)})}})})};export{hn as default};
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .message-quote[data-v-fc970c70]{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-fc970c70]{font-size:.75em;color:#007bff;font-weight:600;margin-bottom:4px;text-transform:uppercase}.quote-header[data-v-fc970c70]{display:flex;align-items:center;margin-bottom:4px;gap:6px}.quote-avatar[data-v-fc970c70]{width:20px;height:20px;border-radius:50%;overflow:hidden;flex-shrink:0}.quote-avatar img[data-v-fc970c70]{width:100%;height:100%;object-fit:cover}.quote-avatar .avatar-placeholder[data-v-fc970c70]{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-fc970c70]{font-weight:600;color:#007bff;font-size:.85em}.quote-time[data-v-fc970c70]{color:#6c757d;font-size:.75em;margin-left:auto}.quote-content[data-v-fc970c70]{color:#7276b7;line-height:1.3;word-wrap:break-word}.quote-content .message-image[data-v-fc970c70]{max-width:200px;max-height:100px}.quote-content .message-image-container[data-v-fc970c70]{margin:2px 0}@media (prefers-color-scheme: dark){.message-quote[data-v-fc970c70]{background-color:#ffffff14;border-left-color:#0d6efd}.quote-content[data-v-fc970c70]{color:#adb5bd}.quote-username[data-v-fc970c70]{color:#0d6efd}}.chat-container[data-v-fc970c70]{display:flex;height:100vh;background:transparent;margin-left:0%;width:100%;overflow:hidden;color:inherit;position:relative}.bot-list[data-v-fc970c70],.channel-list[data-v-fc970c70],.message-area[data-v-fc970c70]{display:flex;flex-direction:column;background:transparent;border-right:1px solid rgba(128,128,128,.2)}.bot-list[data-v-fc970c70]{width:250px;min-width:250px;max-width:250px;flex-shrink:0}.channel-list[data-v-fc970c70]{width:300px;min-width:300px;max-width:300px;flex-shrink:0}.message-area[data-v-fc970c70]{flex:1;border-right:none}.panel-header[data-v-fc970c70]{padding:16px;border-bottom:1px solid rgba(128,128,128,.2);background:transparent;display:flex;align-items:center;justify-content:space-between}.panel-header h3[data-v-fc970c70]{margin:0;font-size:16px;font-weight:600;color:currentColor}.back-button[data-v-fc970c70]{display:none;background:none;border:none;color:currentColor;font-size:18px;cursor:pointer;padding:4px 8px;border-radius:4px;transition:background-color .2s}.back-button[data-v-fc970c70]:hover{background:#8080801a}.bot-items[data-v-fc970c70],.channel-items[data-v-fc970c70]{flex:1;overflow-y:auto;max-height:calc(100vh - 60px)}.bot-item[data-v-fc970c70],.channel-item[data-v-fc970c70]{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-fc970c70]:hover,.channel-item[data-v-fc970c70]:hover{background:#8080801a}.bot-item.active[data-v-fc970c70],.channel-item.active[data-v-fc970c70]{background:#2196f31a;border-right:3px solid #2196f3}.bot-avatar[data-v-fc970c70]{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-fc970c70]{width:100%;height:100%;object-fit:cover}.avatar-placeholder[data-v-fc970c70]{font-size:16px;font-weight:700;color:currentColor;opacity:.7}.bot-info[data-v-fc970c70]{flex:1}.bot-name[data-v-fc970c70]{font-weight:500;color:currentColor;margin-bottom:2px}.bot-platform[data-v-fc970c70]{font-size:12px;color:currentColor;opacity:.7}.bot-status[data-v-fc970c70]{width:8px;height:8px;border-radius:50%;margin-left:8px}.bot-status.online[data-v-fc970c70]{background:#4caf50}.bot-status.offline[data-v-fc970c70]{background:#f44336}.channel-info[data-v-fc970c70]{flex:1}.channel-name[data-v-fc970c70]{font-weight:500;color:currentColor;margin-bottom:2px}.channel-type[data-v-fc970c70]{font-size:12px;color:currentColor;opacity:.7}.channel-message-count[data-v-fc970c70]{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-fc970c70]{cursor:grab;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.channel-message-count.draggable-bubble[data-v-fc970c70]:hover{background:#1976d2;transform:scale(1.1);box-shadow:0 2px 8px #2196f34d}.channel-message-count.draggable-bubble[data-v-fc970c70]:active,.channel-message-count.draggable-bubble.dragging[data-v-fc970c70]{cursor:grabbing;background:#1565c0;box-shadow:0 4px 12px #2196f366}.dragging-clone[data-v-fc970c70]{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-fc970c70]{background:#f44336!important;animation:shake-fc970c70 .3s ease-in-out infinite}@keyframes pulseThreshold-fc970c70{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-fc970c70{0%{transform:translateY(8px);opacity:0}to{transform:translateY(0);opacity:1}}.message-content[data-v-fc970c70]{display:flex;flex-direction:column;height:calc(100vh - 60px);overflow:hidden;position:relative}.message-history[data-v-fc970c70]{flex:1;overflow-y:auto;padding:16px 16px 8px;max-height:calc(100vh - 200px)}.message-item[data-v-fc970c70]{display:flex;margin-bottom:16px;padding:8px;border-radius:8px;transition:background-color .3s ease}.message-item[data-v-fc970c70]:hover{background-color:#8080801a}.message-item.new-message[data-v-fc970c70]{background-color:#4caf5033;animation:highlight-fc970c70 2s ease-out}.message-item.bot-message[data-v-fc970c70]{flex-direction:row-reverse;justify-content:flex-start}.message-item.bot-message .message-avatar[data-v-fc970c70]{margin-right:0;margin-left:12px}.message-item.bot-message .message-content-wrapper[data-v-fc970c70]{display:flex;flex-direction:column;align-items:flex-end}.message-item.bot-message .message-header[data-v-fc970c70]{display:flex;align-items:center;justify-content:flex-end;margin-bottom:4px}.message-item.bot-message .message-username[data-v-fc970c70]{margin-right:0;margin-left:8px;order:2}.message-item.bot-message .message-time[data-v-fc970c70]{order:1}.message-item.bot-message .message-text[data-v-fc970c70]{background-color:#2196f31a;padding:8px 12px;border-radius:12px 12px 4px;display:inline-block;max-width:80%;text-align:left}@keyframes highlight-fc970c70{0%{background-color:#4caf504d}to{background-color:transparent}}.message-avatar[data-v-fc970c70]{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-fc970c70]{width:100%;height:100%;object-fit:cover}.message-avatar .avatar-placeholder[data-v-fc970c70]{font-size:12px;font-weight:700;color:currentColor;opacity:.7}.message-content-wrapper[data-v-fc970c70]{flex:1}.message-header[data-v-fc970c70]{display:flex;align-items:center;margin-bottom:4px}.message-username[data-v-fc970c70]{font-weight:500;color:currentColor;margin-right:8px}.message-time[data-v-fc970c70]{font-size:12px;color:currentColor;opacity:.5}.message-text[data-v-fc970c70]{color:currentColor;line-height:1.4;word-wrap:break-word;word-break:break-word;white-space:pre-wrap;max-width:100%;overflow-wrap:break-word}.message-item:not(.bot-message) .message-text[data-v-fc970c70]{background-color:#8080801a;padding:8px 12px;border-radius:12px 12px 12px 4px;display:inline-block;max-width:80%}.message-input[data-v-fc970c70]{display:flex;flex-direction:column;padding:12px 16px 16px;border-top:1px solid rgba(128,128,128,.2);background:transparent;flex-shrink:0;position:sticky;bottom:0;margin-top:-10px}.input-row[data-v-fc970c70]{display:flex;gap:8px;align-items:center}.floating-scroll-button[data-v-fc970c70]{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-fc970c70]:hover{background:#1976d2;transform:scale(1.1);box-shadow:0 6px 16px #2196f366}.floating-scroll-button[data-v-fc970c70]:active{transform:scale(.95)}.input-row button[data-v-fc970c70]{padding:8px 16px;background:#2196f3;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s}.message-image-container[data-v-fc970c70]{margin:8px 0;max-width:100%;display:block}.message-image[data-v-fc970c70]{border-radius:8px;object-fit:contain;display:block;cursor:pointer;transition:transform .2s ease}.message-image-loading[data-v-fc970c70]{display:inline-block;padding:8px 12px;background:#8080801a;border-radius:4px;color:currentColor;opacity:.7;font-size:12px}.message-image-error[data-v-fc970c70]{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-fc970c70]{display:block;margin-bottom:4px}.message-paragraph[data-v-fc970c70]:last-child{margin-bottom:0}.forward-message-container[data-v-fc970c70]{border:1px solid #ffffff;border-radius:8px;margin:4px 0;overflow:hidden;background:#f9f9f900}.forward-message-preview[data-v-fc970c70]{padding:12px;cursor:pointer;transition:background-color .2s}.forward-message-preview[data-v-fc970c70]:hover{background:#f0f0f0}.forward-message-title[data-v-fc970c70]{font-weight:600;color:#333;margin-bottom:8px;font-size:14px}.forward-message-preview-item[data-v-fc970c70]{color:#666;font-size:13px;margin:2px 0;line-height:1.4}.forward-message-footer[data-v-fc970c70]{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-fc970c70]{color:#2196f3;font-size:12px}.forward-message-toggle[data-v-fc970c70]{color:#666;font-size:12px}.forward-message-expanded[data-v-fc970c70]{border-top:1px solid #e0e0e0;background:#fff;max-height:400px;overflow-y:auto}.forwarded-message-item[data-v-fc970c70]{padding:12px;border-bottom:1px solid #f0f0f0}.forwarded-message-item[data-v-fc970c70]:last-child{border-bottom:none}.forwarded-message-header[data-v-fc970c70]{display:flex;align-items:center;margin-bottom:6px}.forwarded-message-nickname[data-v-fc970c70]{font-weight:600;color:#333;font-size:13px}.forwarded-message-userid[data-v-fc970c70]{color:#999;font-size:11px;margin-left:6px}.forwarded-message-content[data-v-fc970c70]{color:#555;font-size:13px;line-height:1.4}.message-at[data-v-fc970c70]{background:#2196f31a;color:#2196f3;padding:2px 4px;border-radius:3px;font-weight:500;cursor:pointer}.message-unknown[data-v-fc970c70]{background:#ff98001a;color:#ff9800;padding:2px 4px;border-radius:3px;font-style:italic;cursor:help}.input-row input[data-v-fc970c70]{flex:1;min-width:0;padding:8px 12px;border:1px solid rgba(128,128,128,.3);border-radius:4px;outline:none;background:transparent;color:currentColor}.input-row input[data-v-fc970c70]:focus{border-color:#2196f3;box-shadow:0 0 0 2px #2196f333}.input-row input[data-v-fc970c70]::placeholder{color:currentColor;opacity:.5}.input-row button[data-v-fc970c70]{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-fc970c70]:hover:not(:disabled){background:#1976d2}.input-row button[data-v-fc970c70]:disabled{background:#8080804d;cursor:not-allowed}.input-row button.is-sending[data-v-fc970c70]{background:#ffc107!important;color:#333!important;cursor:default!important}.message-input .input-row button.is-sending[data-v-fc970c70]{background:#ffc107!important;color:#333!important;cursor:default!important;border-color:#ffc107!important}.empty-state[data-v-fc970c70]{display:flex;align-items:center;justify-content:center;height:100%;color:currentColor;opacity:.5;font-size:14px}.message-text-content[data-v-fc970c70]{display:inline}.message-image-container[data-v-fc970c70]{display:block;margin:4px 0}.message-image[data-v-fc970c70]{border-radius:8px;margin:4px 0;display:block;cursor:pointer;transition:transform .2s ease;object-fit:contain;background:#8080801a}.message-image[data-v-fc970c70]:hover{transform:scale(1.02)}.message-image-loading[data-v-fc970c70]{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-fc970c70]{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-fc970c70]{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-fc970c70]:hover{background:#2196f333}.message-unknown[data-v-fc970c70]{background:#ff98001a;color:#ff9800;padding:2px 6px;border-radius:4px;font-size:12px;display:inline-block;margin:0 2px;cursor:help}@keyframes pulse-fc970c70{0%,to{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.1)}}.channel-message-count.will-delete[data-v-fc970c70]{background:#f44336!important;animation:shake-fc970c70 .3s ease-in-out infinite}@keyframes shake-fc970c70{0%,to{transform:translate(0)}25%{transform:translate(-2px)}75%{transform:translate(2px)}}body.dragging-bubble-global[data-v-fc970c70]{user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;cursor:grabbing}.drag-threshold-circle[data-v-fc970c70]{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-fc970c70 1.5s ease-in-out infinite}.context-menu[data-v-fc970c70]{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-fc970c70]{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-fc970c70]:last-child{border-bottom:none}.context-menu-item[data-v-fc970c70]:hover{background:#2196f31a;color:#1976d2;transform:translate(2px)}.context-menu-item.danger[data-v-fc970c70]{color:#d32f2f}.context-menu-item.danger[data-v-fc970c70]:hover{background:#f443361a;color:#c62828}.bot-item.pinned[data-v-fc970c70],.channel-item.pinned[data-v-fc970c70]{background:#ffc1071a;border-left:3px solid #ffc107}.bot-item.pinned[data-v-fc970c70]:before,.channel-item.pinned[data-v-fc970c70]:before{content:"📌";position:absolute;left:4px;top:50%;transform:translateY(-50%);font-size:12px;opacity:.7}.bot-item.pinned[data-v-fc970c70],.channel-item.pinned[data-v-fc970c70]{position:relative;padding-left:24px}@media (prefers-color-scheme: dark){.context-menu[data-v-fc970c70]{background:#ffffff26;border-color:#fff3;box-shadow:0 8px 32px #0006}.context-menu-item[data-v-fc970c70]{color:#fff;border-bottom-color:#ffffff1a}.context-menu-item[data-v-fc970c70]:hover{background:#2196f333;color:#64b5f6}.context-menu-item.danger[data-v-fc970c70]{color:#ff8a80}.context-menu-item.danger[data-v-fc970c70]:hover{background:#f4433633;color:#ffab91}.bot-item.pinned[data-v-fc970c70],.channel-item.pinned[data-v-fc970c70]{background:#ffc10726}}.message-share-card[data-v-fc970c70]{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-fc970c70]:hover{transform:translateY(-2px);box-shadow:0 8px 24px #00000026;border-color:#2196f34d}.share-card-preview[data-v-fc970c70]{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-fc970c70]{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-fc970c70]{transform:scale(1.05)}.share-card-content[data-v-fc970c70]{padding:8px}.share-card-header[data-v-fc970c70]{display:flex;align-items:center;margin-bottom:12px;gap:12px}.share-card-icon[data-v-fc970c70]{width:32px;height:32px;border-radius:8px;object-fit:cover;flex-shrink:0}.share-card-app-info[data-v-fc970c70]{flex:1;min-width:0}.share-card-app-name[data-v-fc970c70]{font-size:12px;color:currentColor;opacity:.7;margin-bottom:2px;font-weight:500}.share-card-title[data-v-fc970c70]{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-fc970c70]{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-fc970c70]{font-size:12px;color:#2196f3;font-weight:500;display:flex;align-items:center;gap:4px}.share-card-link-hint[data-v-fc970c70]:after{content:"→";transition:transform .2s ease}.message-share-card:hover .share-card-link-hint[data-v-fc970c70]:after{transform:translate(2px)}.message-json-error[data-v-fc970c70],.message-json-raw[data-v-fc970c70]{display:inline-block;margin:8px 0;max-width:400px}.json-error-text[data-v-fc970c70]{color:#f44336;font-size:14px;font-weight:500}.json-label[data-v-fc970c70]{color:currentColor;opacity:.7;font-size:12px;font-weight:500;margin-bottom:8px}.json-raw-data[data-v-fc970c70]{margin-top:8px}.json-raw-data summary[data-v-fc970c70]{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-fc970c70]:hover{background:#2196f333}.json-raw-content[data-v-fc970c70]{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;max-height:200px;overflow-y:auto;border:1px solid rgba(128,128,128,.2)}@media (prefers-color-scheme: dark){.message-share-card[data-v-fc970c70]{background:#ffffff14;border-color:#ffffff26}.message-share-card[data-v-fc970c70]:hover{border-color:#2196f380;box-shadow:0 8px 24px #0000004d}.json-raw-content[data-v-fc970c70]{background:#ffffff0d;border-color:#ffffff1a}}@media (max-width: 768px){.chat-container[data-v-fc970c70]{position:relative}.bot-list[data-v-fc970c70],.channel-list[data-v-fc970c70],.message-area[data-v-fc970c70]{position:absolute;top:0;left:0;width:100%;height:100%;transition:transform .3s ease;z-index:1}.bot-list[data-v-fc970c70]{transform:translate(0);z-index:3}.channel-list[data-v-fc970c70]{transform:translate(100%);z-index:2}.message-area[data-v-fc970c70]{transform:translate(200%);z-index:1}.chat-container.show-channels .bot-list[data-v-fc970c70]{transform:translate(-100%)}.chat-container.show-channels .channel-list[data-v-fc970c70]{transform:translate(0);z-index:3}.chat-container.show-channels .message-area[data-v-fc970c70]{transform:translate(100%)}.chat-container.show-messages .bot-list[data-v-fc970c70]{transform:translate(-200%)}.chat-container.show-messages .channel-list[data-v-fc970c70]{transform:translate(-100%)}.chat-container.show-messages .message-area[data-v-fc970c70]{transform:translate(0);z-index:3}.back-button[data-v-fc970c70]{display:none!important}.panel-header[data-v-fc970c70]{flex-direction:row-reverse;position:sticky;top:0;z-index:5;background:inherit}.panel-header h3[data-v-fc970c70]{text-align:right}.floating-scroll-button[data-v-fc970c70]{right:16px;bottom:70px;width:40px;height:40px}.message-input[data-v-fc970c70]{padding:8px 12px 12px;position:fixed;bottom:0;left:0;right:0;background:inherit;border-top:1px solid rgba(128,128,128,.2);z-index:10}.input-row input[data-v-fc970c70]{font-size:16px;padding:10px 12px}.input-row button[data-v-fc970c70]{padding:10px 16px;font-size:16px}.message-history[data-v-fc970c70]{padding:12px 12px 80px;max-height:calc(100vh - 140px)}.message-item[data-v-fc970c70]{margin-bottom:12px;padding:6px}.message-avatar[data-v-fc970c70]{width:28px;height:28px;margin-right:8px}.message-item.bot-message .message-avatar[data-v-fc970c70]{margin-left:8px}.message-image[data-v-fc970c70]{max-width:280px;max-height:160px}.quote-content .message-image[data-v-fc970c70]{max-width:150px;max-height:80px}.context-menu[data-v-fc970c70]{min-width:160px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}.context-menu-item[data-v-fc970c70]{padding:14px 16px;font-size:16px}.bot-item[data-v-fc970c70],.channel-item[data-v-fc970c70]{padding:14px 16px}.bot-avatar[data-v-fc970c70]{width:36px;height:36px;margin-right:10px}.bot-name[data-v-fc970c70],.channel-name[data-v-fc970c70]{font-size:15px}.bot-platform[data-v-fc970c70],.channel-type[data-v-fc970c70]{font-size:13px}}@media (min-width: 769px) and (max-width: 1024px){.bot-list[data-v-fc970c70]{width:220px;min-width:220px;max-width:220px}.channel-list[data-v-fc970c70]{width:280px;min-width:280px;max-width:280px}.message-image[data-v-fc970c70]{max-width:350px;max-height:180px}}.chat-container.swiping[data-v-fc970c70]{overflow:hidden}.bot-list.swiping[data-v-fc970c70],.channel-list.swiping[data-v-fc970c70],.message-area.swiping[data-v-fc970c70]{transition:none!important}.swipe-indicator[data-v-fc970c70]{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-fc970c70]{opacity:1}.message-area .message-content[data-v-fc970c70]{padding-bottom:80px}.image-preview-container[data-v-fc970c70]{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-fc970c70]{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-fc970c70]{width:100%;height:100%;object-fit:cover;display:block}.remove-image-btn[data-v-fc970c70]{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-fc970c70]:hover{background:#d32f2f;transform:scale(1.1)}.input-actions[data-v-fc970c70]{position:relative;margin-right:8px}.add-button[data-v-fc970c70]{width:36px;height:36px;border-radius:12px;background:linear-gradient(135deg,#667eea,#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-fc970c70]:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(135deg,#fff3,#ffffff1a);border-radius:12px;opacity:0;transition:opacity .3s ease}.add-button[data-v-fc970c70]:hover{transform:translateY(-2px) scale(1.05);box-shadow:0 4px 16px #667eea66}.add-button[data-v-fc970c70]:hover:before{opacity:1}.add-button.active[data-v-fc970c70]{background:linear-gradient(135deg,#f093fb,#f5576c);transform:translateY(-2px) scale(1.05) rotate(45deg);box-shadow:0 4px 16px #f5576c66}.add-button[data-v-fc970c70]:active{transform:translateY(0) scale(.98);transition:all .1s ease}.action-menu[data-v-fc970c70]{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-fc970c70 .3s cubic-bezier(.4,0,.2,1) forwards}.action-menu-item[data-v-fc970c70]{display:flex;align-items:center;gap:12px;padding:14px 18px;background:none;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-fc970c70]:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:linear-gradient(135deg,#667eea,#764ba2);transform:scaleY(0);transition:transform .2s cubic-bezier(.4,0,.2,1)}.action-menu-item[data-v-fc970c70]:hover{background:linear-gradient(90deg,#667eea14,#764ba214);color:#667eea;transform:translate(4px)}.action-menu-item[data-v-fc970c70]:hover:before{transform:scaleY(1)}.action-menu-item svg[data-v-fc970c70]{flex-shrink:0}@media (prefers-color-scheme: dark){.action-menu[data-v-fc970c70]{background:#1e1e1efa;box-shadow:0 8px 32px #0000004d,0 2px 8px #0003}.action-menu-item[data-v-fc970c70]{color:#fff}.action-menu-item[data-v-fc970c70]:before{background:linear-gradient(135deg,#4facfe,#00f2fe)}.action-menu-item[data-v-fc970c70]:hover{background:linear-gradient(90deg,#4facfe1f,#00f2fe1f);color:#4facfe}.add-button[data-v-fc970c70]{background:linear-gradient(135deg,#4facfe,#00f2fe);box-shadow:0 2px 8px #4facfe4d}.add-button[data-v-fc970c70]:hover{box-shadow:0 4px 16px #4facfe66}.add-button.active[data-v-fc970c70]{background:linear-gradient(135deg,#fa709a,#fee140);box-shadow:0 4px 16px #fa709a66}.image-preview-item[data-v-fc970c70]{border-color:#64b5f680;background:#ffffff0d}}@media (max-width: 768px){.image-preview-container[data-v-fc970c70]{padding:6px 0;margin-bottom:6px}.image-preview-item[data-v-fc970c70]{width:50px;height:50px}.add-button[data-v-fc970c70]{width:32px;height:32px;border-radius:10px}.action-menu[data-v-fc970c70]{min-width:100px}.action-menu-item[data-v-fc970c70]{padding:10px 12px;font-size:13px}.remove-image-btn[data-v-fc970c70]{width:18px;height:18px;top:-5px;right:-5px}}.message-history[data-v-fc970c70]::-webkit-scrollbar{width:6px}.message-history[data-v-fc970c70]::-webkit-scrollbar-track{background:transparent}.message-history[data-v-fc970c70]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.message-history[data-v-fc970c70]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.bot-items[data-v-fc970c70]::-webkit-scrollbar{width:6px}.bot-items[data-v-fc970c70]::-webkit-scrollbar-track{background:transparent}.bot-items[data-v-fc970c70]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.bot-items[data-v-fc970c70]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.channel-items[data-v-fc970c70]::-webkit-scrollbar{width:6px}.channel-items[data-v-fc970c70]::-webkit-scrollbar-track{background:transparent}.channel-items[data-v-fc970c70]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.channel-items[data-v-fc970c70]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.forward-message-expanded[data-v-fc970c70]::-webkit-scrollbar{width:6px}.forward-message-expanded[data-v-fc970c70]::-webkit-scrollbar-track{background:transparent}.forward-message-expanded[data-v-fc970c70]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.forward-message-expanded[data-v-fc970c70]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.json-raw-content[data-v-fc970c70]::-webkit-scrollbar{width:6px}.json-raw-content[data-v-fc970c70]::-webkit-scrollbar-track{background:transparent}.json-raw-content[data-v-fc970c70]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.json-raw-content[data-v-fc970c70]::-webkit-scrollbar-thumb:hover{background-color:#90939980}@media (prefers-color-scheme: dark){.message-history[data-v-fc970c70]::-webkit-scrollbar-thumb,.bot-items[data-v-fc970c70]::-webkit-scrollbar-thumb,.channel-items[data-v-fc970c70]::-webkit-scrollbar-thumb,.forward-message-expanded[data-v-fc970c70]::-webkit-scrollbar-thumb,.json-raw-content[data-v-fc970c70]::-webkit-scrollbar-thumb{background-color:#fff3}.message-history[data-v-fc970c70]::-webkit-scrollbar-thumb:hover,.bot-items[data-v-fc970c70]::-webkit-scrollbar-thumb:hover,.channel-items[data-v-fc970c70]::-webkit-scrollbar-thumb:hover,.forward-message-expanded[data-v-fc970c70]::-webkit-scrollbar-thumb:hover,.json-raw-content[data-v-fc970c70]::-webkit-scrollbar-thumb:hover{background-color:#fff6}}.layout-iframe{width:100%;height:100%;border:none}
1
+ .message-quote[data-v-323dce07]{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-323dce07]{font-size:.75em;color:#007bff;font-weight:600;margin-bottom:4px;text-transform:uppercase}.quote-header[data-v-323dce07]{display:flex;align-items:center;margin-bottom:4px;gap:6px}.quote-avatar[data-v-323dce07]{width:20px;height:20px;border-radius:50%;overflow:hidden;flex-shrink:0}.quote-avatar img[data-v-323dce07]{width:100%;height:100%;object-fit:cover}.quote-avatar .avatar-placeholder[data-v-323dce07]{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-323dce07]{font-weight:600;color:#007bff;font-size:.85em}.quote-time[data-v-323dce07]{color:#6c757d;font-size:.75em;margin-left:auto}.quote-content[data-v-323dce07]{color:#7276b7;line-height:1.3;word-wrap:break-word}.quote-content .message-image[data-v-323dce07]{max-width:200px;max-height:100px}.quote-content .message-image-container[data-v-323dce07]{margin:2px 0}@media (prefers-color-scheme: dark){.message-quote[data-v-323dce07]{background-color:#ffffff14;border-left-color:#0d6efd}.quote-content[data-v-323dce07]{color:#adb5bd}.quote-username[data-v-323dce07]{color:#0d6efd}}.chat-container[data-v-323dce07]{display:flex;height:100vh;background:transparent;margin-left:0%;width:100%;overflow:hidden;color:inherit;position:relative}.bot-list[data-v-323dce07],.channel-list[data-v-323dce07],.message-area[data-v-323dce07]{display:flex;flex-direction:column;background:transparent;border-right:1px solid rgba(128,128,128,.2)}.bot-list[data-v-323dce07]{width:250px;min-width:250px;max-width:250px;flex-shrink:0}.channel-list[data-v-323dce07]{width:300px;min-width:300px;max-width:300px;flex-shrink:0}.message-area[data-v-323dce07]{flex:1;border-right:none}.panel-header[data-v-323dce07]{padding:16px;border-bottom:1px solid rgba(128,128,128,.2);background:transparent;display:flex;align-items:center;justify-content:space-between}.panel-header h3[data-v-323dce07]{margin:0;font-size:16px;font-weight:600;color:currentColor}.back-button[data-v-323dce07]{display:none;background:none;border:none;color:currentColor;font-size:18px;cursor:pointer;padding:4px 8px;border-radius:4px;transition:background-color .2s}.back-button[data-v-323dce07]:hover{background:#8080801a}.bot-items[data-v-323dce07],.channel-items[data-v-323dce07]{flex:1;overflow-y:auto;max-height:calc(100vh - 60px)}.bot-item[data-v-323dce07],.channel-item[data-v-323dce07]{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-323dce07]:hover,.channel-item[data-v-323dce07]:hover{background:#8080801a}.bot-item.active[data-v-323dce07],.channel-item.active[data-v-323dce07]{background:#2196f31a;border-right:3px solid #2196f3}.bot-avatar[data-v-323dce07]{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-323dce07]{width:100%;height:100%;object-fit:cover}.avatar-placeholder[data-v-323dce07]{font-size:16px;font-weight:700;color:currentColor;opacity:.7}.bot-info[data-v-323dce07]{flex:1}.bot-name[data-v-323dce07]{font-weight:500;color:currentColor;margin-bottom:2px}.bot-platform[data-v-323dce07]{font-size:12px;color:currentColor;opacity:.7}.bot-status[data-v-323dce07]{width:8px;height:8px;border-radius:50%;margin-left:8px}.bot-status.online[data-v-323dce07]{background:#4caf50}.bot-status.offline[data-v-323dce07]{background:#f44336}.channel-info[data-v-323dce07]{flex:1}.channel-name[data-v-323dce07]{font-weight:500;color:currentColor;margin-bottom:2px}.channel-type[data-v-323dce07]{font-size:12px;color:currentColor;opacity:.7}.channel-message-count[data-v-323dce07]{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-323dce07]{cursor:grab;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.channel-message-count.draggable-bubble[data-v-323dce07]:hover{background:#1976d2;transform:scale(1.1);box-shadow:0 2px 8px #2196f34d}.channel-message-count.draggable-bubble[data-v-323dce07]:active,.channel-message-count.draggable-bubble.dragging[data-v-323dce07]{cursor:grabbing;background:#1565c0;box-shadow:0 4px 12px #2196f366}.dragging-clone[data-v-323dce07]{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-323dce07]{background:#f44336!important;animation:shake-323dce07 .3s ease-in-out infinite}@keyframes pulseThreshold-323dce07{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-323dce07{0%{transform:translateY(8px);opacity:0}to{transform:translateY(0);opacity:1}}.message-content[data-v-323dce07]{display:flex;flex-direction:column;height:calc(100vh - 60px);overflow:hidden;position:relative}.message-history[data-v-323dce07]{flex:1;overflow-y:auto;padding:16px 16px 8px;max-height:calc(100vh - 200px)}.message-item[data-v-323dce07]{display:flex;margin-bottom:16px;padding:8px;border-radius:8px;transition:background-color .3s ease}.message-item[data-v-323dce07]:hover{background-color:#8080801a}.message-item.new-message[data-v-323dce07]{background-color:#4caf5033;animation:highlight-323dce07 2s ease-out}.message-item.bot-message[data-v-323dce07]{flex-direction:row-reverse;justify-content:flex-start}.message-item.bot-message .message-avatar[data-v-323dce07]{margin-right:0;margin-left:12px}.message-item.bot-message .message-content-wrapper[data-v-323dce07]{display:flex;flex-direction:column;align-items:flex-end}.message-item.bot-message .message-header[data-v-323dce07]{display:flex;align-items:center;justify-content:flex-end;margin-bottom:4px}.message-item.bot-message .message-username[data-v-323dce07]{margin-right:0;margin-left:8px;order:2}.message-item.bot-message .message-time[data-v-323dce07]{order:1}.message-item.bot-message .message-text[data-v-323dce07]{background-color:#2196f31a;padding:8px 12px;border-radius:12px 12px 4px;display:inline-block;max-width:80%;text-align:left}@keyframes highlight-323dce07{0%{background-color:#4caf504d}to{background-color:transparent}}.message-avatar[data-v-323dce07]{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-323dce07]{width:100%;height:100%;object-fit:cover}.message-avatar .avatar-placeholder[data-v-323dce07]{font-size:12px;font-weight:700;color:currentColor;opacity:.7}.message-content-wrapper[data-v-323dce07]{flex:1}.message-header[data-v-323dce07]{display:flex;align-items:center;margin-bottom:4px}.message-username[data-v-323dce07]{font-weight:500;color:currentColor;margin-right:8px}.message-time[data-v-323dce07]{font-size:12px;color:currentColor;opacity:.5}.message-text[data-v-323dce07]{color:currentColor;line-height:1.4;word-wrap:break-word;word-break:break-word;white-space:pre-wrap;max-width:100%;overflow-wrap:break-word}.message-item:not(.bot-message) .message-text[data-v-323dce07]{background-color:#8080801a;padding:8px 12px;border-radius:12px 12px 12px 4px;display:inline-block;max-width:80%}.message-input[data-v-323dce07]{display:flex;flex-direction:column;padding:12px 16px 16px;border-top:1px solid rgba(128,128,128,.2);background:transparent;flex-shrink:0;position:sticky;bottom:0;margin-top:-10px}.input-row[data-v-323dce07]{display:flex;gap:8px;align-items:center}.floating-scroll-button[data-v-323dce07]{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-323dce07]:hover{background:#1976d2;transform:scale(1.1);box-shadow:0 6px 16px #2196f366}.floating-scroll-button[data-v-323dce07]:active{transform:scale(.95)}.input-row button[data-v-323dce07]{padding:8px 16px;background:#2196f3;color:#fff;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s}.message-image-container[data-v-323dce07]{margin:8px 0;max-width:100%;display:block}.message-image[data-v-323dce07]{border-radius:8px;object-fit:contain;display:block;cursor:pointer;transition:transform .2s ease}.message-image-loading[data-v-323dce07]{display:inline-block;padding:8px 12px;background:#8080801a;border-radius:4px;color:currentColor;opacity:.7;font-size:12px}.message-image-error[data-v-323dce07]{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-323dce07]{display:block;margin-bottom:4px}.message-paragraph[data-v-323dce07]:last-child{margin-bottom:0}.forward-message-container[data-v-323dce07]{border:1px solid #ffffff;border-radius:8px;margin:4px 0;overflow:hidden;background:#f9f9f900}.forward-message-preview[data-v-323dce07]{padding:12px;cursor:pointer;transition:background-color .2s}.forward-message-preview[data-v-323dce07]:hover{background:#f0f0f0}.forward-message-title[data-v-323dce07]{font-weight:600;color:#333;margin-bottom:8px;font-size:14px}.forward-message-preview-item[data-v-323dce07]{color:#666;font-size:13px;margin:2px 0;line-height:1.4}.forward-message-footer[data-v-323dce07]{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-323dce07]{color:#2196f3;font-size:12px}.forward-message-toggle[data-v-323dce07]{color:#666;font-size:12px}.forward-message-expanded[data-v-323dce07]{border-top:1px solid #e0e0e0;background:#fff;max-height:400px;overflow-y:auto}.forwarded-message-item[data-v-323dce07]{padding:12px;border-bottom:1px solid #f0f0f0}.forwarded-message-item[data-v-323dce07]:last-child{border-bottom:none}.forwarded-message-header[data-v-323dce07]{display:flex;align-items:center;margin-bottom:6px}.forwarded-message-nickname[data-v-323dce07]{font-weight:600;color:#333;font-size:13px}.forwarded-message-userid[data-v-323dce07]{color:#999;font-size:11px;margin-left:6px}.forwarded-message-content[data-v-323dce07]{color:#555;font-size:13px;line-height:1.4}.message-at[data-v-323dce07]{background:#2196f31a;color:#2196f3;padding:2px 4px;border-radius:3px;font-weight:500;cursor:pointer}.message-unknown[data-v-323dce07]{background:#ff98001a;color:#ff9800;padding:2px 4px;border-radius:3px;font-style:italic;cursor:help}.input-row input[data-v-323dce07]{flex:1;min-width:0;padding:8px 12px;border:1px solid rgba(128,128,128,.3);border-radius:4px;outline:none;background:transparent;color:currentColor}.input-row input[data-v-323dce07]:focus{border-color:#2196f3;box-shadow:0 0 0 2px #2196f333}.input-row input[data-v-323dce07]::placeholder{color:currentColor;opacity:.5}.input-row button[data-v-323dce07]{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-323dce07]:hover:not(:disabled){background:#1976d2}.input-row button[data-v-323dce07]:disabled{background:#8080804d;cursor:not-allowed}.input-row button.is-sending[data-v-323dce07]{background:#ffc107!important;color:#333!important;cursor:default!important}.message-input .input-row button.is-sending[data-v-323dce07]{background:#ffc107!important;color:#333!important;cursor:default!important;border-color:#ffc107!important}.empty-state[data-v-323dce07]{display:flex;align-items:center;justify-content:center;height:100%;color:currentColor;opacity:.5;font-size:14px}.message-text-content[data-v-323dce07]{display:inline}.message-image-container[data-v-323dce07]{display:block;margin:4px 0}.message-image[data-v-323dce07]{border-radius:8px;margin:4px 0;display:block;cursor:pointer;transition:transform .2s ease;object-fit:contain;background:#8080801a}.message-image[data-v-323dce07]:hover{transform:scale(1.02)}.message-image-loading[data-v-323dce07]{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-323dce07]{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-323dce07]{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-323dce07]:hover{background:#2196f333}.message-unknown[data-v-323dce07]{background:#ff98001a;color:#ff9800;padding:2px 6px;border-radius:4px;font-size:12px;display:inline-block;margin:0 2px;cursor:help}@keyframes pulse-323dce07{0%,to{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.1)}}.channel-message-count.will-delete[data-v-323dce07]{background:#f44336!important;animation:shake-323dce07 .3s ease-in-out infinite}@keyframes shake-323dce07{0%,to{transform:translate(0)}25%{transform:translate(-2px)}75%{transform:translate(2px)}}body.dragging-bubble-global[data-v-323dce07]{user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;cursor:grabbing}.drag-threshold-circle[data-v-323dce07]{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-323dce07 1.5s ease-in-out infinite}.context-menu[data-v-323dce07]{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-323dce07]{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-323dce07]:last-child{border-bottom:none}.context-menu-item[data-v-323dce07]:hover{background:#2196f31a;color:#1976d2;transform:translate(2px)}.context-menu-item.danger[data-v-323dce07]{color:#d32f2f}.context-menu-item.danger[data-v-323dce07]:hover{background:#f443361a;color:#c62828}.bot-item.pinned[data-v-323dce07],.channel-item.pinned[data-v-323dce07]{background:#ffc1071a;border-left:3px solid #ffc107}.bot-item.pinned[data-v-323dce07]:before,.channel-item.pinned[data-v-323dce07]:before{content:"📌";position:absolute;left:4px;top:50%;transform:translateY(-50%);font-size:12px;opacity:.7}.bot-item.pinned[data-v-323dce07],.channel-item.pinned[data-v-323dce07]{position:relative;padding-left:24px}@media (prefers-color-scheme: dark){.context-menu[data-v-323dce07]{background:#ffffff26;border-color:#fff3;box-shadow:0 8px 32px #0006}.context-menu-item[data-v-323dce07]{color:#fff;border-bottom-color:#ffffff1a}.context-menu-item[data-v-323dce07]:hover{background:#2196f333;color:#64b5f6}.context-menu-item.danger[data-v-323dce07]{color:#ff8a80}.context-menu-item.danger[data-v-323dce07]:hover{background:#f4433633;color:#ffab91}.bot-item.pinned[data-v-323dce07],.channel-item.pinned[data-v-323dce07]{background:#ffc10726}}.message-share-card[data-v-323dce07]{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-323dce07]:hover{transform:translateY(-2px);box-shadow:0 8px 24px #00000026;border-color:#2196f34d}.share-card-preview[data-v-323dce07]{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-323dce07]{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-323dce07]{transform:scale(1.05)}.share-card-content[data-v-323dce07]{padding:8px}.share-card-header[data-v-323dce07]{display:flex;align-items:center;margin-bottom:12px;gap:12px}.share-card-icon[data-v-323dce07]{width:32px;height:32px;border-radius:8px;object-fit:cover;flex-shrink:0}.share-card-app-info[data-v-323dce07]{flex:1;min-width:0}.share-card-app-name[data-v-323dce07]{font-size:12px;color:currentColor;opacity:.7;margin-bottom:2px;font-weight:500}.share-card-title[data-v-323dce07]{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-323dce07]{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-323dce07]{font-size:12px;color:#2196f3;font-weight:500;display:flex;align-items:center;gap:4px}.share-card-link-hint[data-v-323dce07]:after{content:"→";transition:transform .2s ease}.message-share-card:hover .share-card-link-hint[data-v-323dce07]:after{transform:translate(2px)}.message-json-error[data-v-323dce07],.message-json-raw[data-v-323dce07]{display:inline-block;margin:8px 0;max-width:400px}.json-error-text[data-v-323dce07]{color:#f44336;font-size:14px;font-weight:500}.json-label[data-v-323dce07]{color:currentColor;opacity:.7;font-size:12px;font-weight:500;margin-bottom:8px}.json-raw-data[data-v-323dce07]{margin-top:8px}.json-raw-data summary[data-v-323dce07]{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-323dce07]:hover{background:#2196f333}.json-raw-content[data-v-323dce07]{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;max-height:200px;overflow-y:auto;border:1px solid rgba(128,128,128,.2)}@media (prefers-color-scheme: dark){.message-share-card[data-v-323dce07]{background:#ffffff14;border-color:#ffffff26}.message-share-card[data-v-323dce07]:hover{border-color:#2196f380;box-shadow:0 8px 24px #0000004d}.json-raw-content[data-v-323dce07]{background:#ffffff0d;border-color:#ffffff1a}}@media (max-width: 768px){.chat-container[data-v-323dce07]{position:relative}.bot-list[data-v-323dce07],.channel-list[data-v-323dce07],.message-area[data-v-323dce07]{position:absolute;top:0;left:0;width:100%;height:100%;transition:transform .3s ease;z-index:1}.bot-list[data-v-323dce07]{transform:translate(0);z-index:3}.channel-list[data-v-323dce07]{transform:translate(100%);z-index:2}.message-area[data-v-323dce07]{transform:translate(200%);z-index:1}.chat-container.show-channels .bot-list[data-v-323dce07]{transform:translate(-100%)}.chat-container.show-channels .channel-list[data-v-323dce07]{transform:translate(0);z-index:3}.chat-container.show-channels .message-area[data-v-323dce07]{transform:translate(100%)}.chat-container.show-messages .bot-list[data-v-323dce07]{transform:translate(-200%)}.chat-container.show-messages .channel-list[data-v-323dce07]{transform:translate(-100%)}.chat-container.show-messages .message-area[data-v-323dce07]{transform:translate(0);z-index:3}.back-button[data-v-323dce07]{display:none!important}.panel-header[data-v-323dce07]{flex-direction:row-reverse;position:sticky;top:0;z-index:5;background:inherit}.panel-header h3[data-v-323dce07]{text-align:right}.floating-scroll-button[data-v-323dce07]{right:16px;bottom:70px;width:40px;height:40px}.message-input[data-v-323dce07]{padding:8px 12px 12px;position:fixed;bottom:0;left:0;right:0;background:inherit;border-top:1px solid rgba(128,128,128,.2);z-index:10}.input-row input[data-v-323dce07]{font-size:16px;padding:10px 12px}.input-row button[data-v-323dce07]{padding:10px 16px;font-size:16px}.message-history[data-v-323dce07]{padding:12px 12px 80px;max-height:calc(100vh - 140px)}.message-item[data-v-323dce07]{margin-bottom:12px;padding:6px}.message-avatar[data-v-323dce07]{width:28px;height:28px;margin-right:8px}.message-item.bot-message .message-avatar[data-v-323dce07]{margin-left:8px}.message-image[data-v-323dce07]{max-width:280px;max-height:160px}.quote-content .message-image[data-v-323dce07]{max-width:150px;max-height:80px}.context-menu[data-v-323dce07]{min-width:160px;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}.context-menu-item[data-v-323dce07]{padding:14px 16px;font-size:16px}.bot-item[data-v-323dce07],.channel-item[data-v-323dce07]{padding:14px 16px}.bot-avatar[data-v-323dce07]{width:36px;height:36px;margin-right:10px}.bot-name[data-v-323dce07],.channel-name[data-v-323dce07]{font-size:15px}.bot-platform[data-v-323dce07],.channel-type[data-v-323dce07]{font-size:13px}}@media (min-width: 769px) and (max-width: 1024px){.bot-list[data-v-323dce07]{width:220px;min-width:220px;max-width:220px}.channel-list[data-v-323dce07]{width:280px;min-width:280px;max-width:280px}.message-image[data-v-323dce07]{max-width:350px;max-height:180px}}.chat-container.swiping[data-v-323dce07]{overflow:hidden}.bot-list.swiping[data-v-323dce07],.channel-list.swiping[data-v-323dce07],.message-area.swiping[data-v-323dce07]{transition:none!important}.swipe-indicator[data-v-323dce07]{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-323dce07]{opacity:1}.message-area .message-content[data-v-323dce07]{padding-bottom:80px}.image-preview-container[data-v-323dce07]{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-323dce07]{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-323dce07]{width:100%;height:100%;object-fit:cover;display:block}.remove-image-btn[data-v-323dce07]{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-323dce07]:hover{background:#d32f2f;transform:scale(1.1)}.input-actions[data-v-323dce07]{position:relative;margin-right:8px}.add-button[data-v-323dce07]{width:36px;height:36px;border-radius:12px;background:linear-gradient(135deg,#667eea,#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-323dce07]:before{content:"";position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(135deg,#fff3,#ffffff1a);border-radius:12px;opacity:0;transition:opacity .3s ease}.add-button[data-v-323dce07]:hover{transform:translateY(-2px) scale(1.05);box-shadow:0 4px 16px #667eea66}.add-button[data-v-323dce07]:hover:before{opacity:1}.add-button.active[data-v-323dce07]{background:linear-gradient(135deg,#f093fb,#f5576c);transform:translateY(-2px) scale(1.05) rotate(45deg);box-shadow:0 4px 16px #f5576c66}.add-button[data-v-323dce07]:active{transform:translateY(0) scale(.98);transition:all .1s ease}.action-menu[data-v-323dce07]{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-323dce07 .3s cubic-bezier(.4,0,.2,1) forwards}.action-menu-item[data-v-323dce07]{display:flex;align-items:center;gap:12px;padding:14px 18px;background:none;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-323dce07]:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:linear-gradient(135deg,#667eea,#764ba2);transform:scaleY(0);transition:transform .2s cubic-bezier(.4,0,.2,1)}.action-menu-item[data-v-323dce07]:hover{background:linear-gradient(90deg,#667eea14,#764ba214);color:#667eea;transform:translate(4px)}.action-menu-item[data-v-323dce07]:hover:before{transform:scaleY(1)}.action-menu-item svg[data-v-323dce07]{flex-shrink:0}@media (prefers-color-scheme: dark){.action-menu[data-v-323dce07]{background:#1e1e1efa;box-shadow:0 8px 32px #0000004d,0 2px 8px #0003}.action-menu-item[data-v-323dce07]{color:#fff}.action-menu-item[data-v-323dce07]:before{background:linear-gradient(135deg,#4facfe,#00f2fe)}.action-menu-item[data-v-323dce07]:hover{background:linear-gradient(90deg,#4facfe1f,#00f2fe1f);color:#4facfe}.add-button[data-v-323dce07]{background:linear-gradient(135deg,#4facfe,#00f2fe);box-shadow:0 2px 8px #4facfe4d}.add-button[data-v-323dce07]:hover{box-shadow:0 4px 16px #4facfe66}.add-button.active[data-v-323dce07]{background:linear-gradient(135deg,#fa709a,#fee140);box-shadow:0 4px 16px #fa709a66}.image-preview-item[data-v-323dce07]{border-color:#64b5f680;background:#ffffff0d}}@media (max-width: 768px){.image-preview-container[data-v-323dce07]{padding:6px 0;margin-bottom:6px}.image-preview-item[data-v-323dce07]{width:50px;height:50px}.add-button[data-v-323dce07]{width:32px;height:32px;border-radius:10px}.action-menu[data-v-323dce07]{min-width:100px}.action-menu-item[data-v-323dce07]{padding:10px 12px;font-size:13px}.remove-image-btn[data-v-323dce07]{width:18px;height:18px;top:-5px;right:-5px}}.message-history[data-v-323dce07]::-webkit-scrollbar{width:6px}.message-history[data-v-323dce07]::-webkit-scrollbar-track{background:transparent}.message-history[data-v-323dce07]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.message-history[data-v-323dce07]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.bot-items[data-v-323dce07]::-webkit-scrollbar{width:6px}.bot-items[data-v-323dce07]::-webkit-scrollbar-track{background:transparent}.bot-items[data-v-323dce07]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.bot-items[data-v-323dce07]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.channel-items[data-v-323dce07]::-webkit-scrollbar{width:6px}.channel-items[data-v-323dce07]::-webkit-scrollbar-track{background:transparent}.channel-items[data-v-323dce07]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.channel-items[data-v-323dce07]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.forward-message-expanded[data-v-323dce07]::-webkit-scrollbar{width:6px}.forward-message-expanded[data-v-323dce07]::-webkit-scrollbar-track{background:transparent}.forward-message-expanded[data-v-323dce07]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.forward-message-expanded[data-v-323dce07]::-webkit-scrollbar-thumb:hover{background-color:#90939980}.json-raw-content[data-v-323dce07]::-webkit-scrollbar{width:6px}.json-raw-content[data-v-323dce07]::-webkit-scrollbar-track{background:transparent}.json-raw-content[data-v-323dce07]::-webkit-scrollbar-thumb{background-color:#9093994d;border-radius:4px;transition:background-color .3s}.json-raw-content[data-v-323dce07]::-webkit-scrollbar-thumb:hover{background-color:#90939980}@media (prefers-color-scheme: dark){.message-history[data-v-323dce07]::-webkit-scrollbar-thumb,.bot-items[data-v-323dce07]::-webkit-scrollbar-thumb,.channel-items[data-v-323dce07]::-webkit-scrollbar-thumb,.forward-message-expanded[data-v-323dce07]::-webkit-scrollbar-thumb,.json-raw-content[data-v-323dce07]::-webkit-scrollbar-thumb{background-color:#fff3}.message-history[data-v-323dce07]::-webkit-scrollbar-thumb:hover,.bot-items[data-v-323dce07]::-webkit-scrollbar-thumb:hover,.channel-items[data-v-323dce07]::-webkit-scrollbar-thumb:hover,.forward-message-expanded[data-v-323dce07]::-webkit-scrollbar-thumb:hover,.json-raw-content[data-v-323dce07]::-webkit-scrollbar-thumb:hover{background-color:#fff6}}.layout-iframe{width:100%;height:100%;border:none}
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.8",
4
+ "version": "1.0.10",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
@@ -1,17 +0,0 @@
1
- import { Context } from 'koishi';
2
- import { Config } from './config';
3
- import { FileManager } from './file-manager';
4
- export declare class ApiHandlers {
5
- private ctx;
6
- private config;
7
- private fileManager;
8
- private logger;
9
- constructor(ctx: Context, config: Config, fileManager: FileManager);
10
- registerApiHandlers(): void;
11
- private isFileUrl;
12
- private createFileUrl;
13
- private handleLocalFileRequest;
14
- private setupTempFileCleanup;
15
- private cleanupTempImagesByCount;
16
- private logInfo;
17
- }
package/lib/config.d.ts DELETED
@@ -1,13 +0,0 @@
1
- import { Schema } from 'koishi';
2
- export interface Config {
3
- loggerinfo: boolean;
4
- maxMessagesPerChannel: number;
5
- keepMessagesOnClear: number;
6
- keepTempImages: number;
7
- blockedPlatforms: Array<{
8
- platformName: string;
9
- exactMatch: boolean;
10
- }>;
11
- chatContainerHeight: number;
12
- }
13
- export declare const Config: Schema<Config>;
@@ -1,18 +0,0 @@
1
- import { Context } from 'koishi';
2
- import { ChatData, MessageInfo } from './types';
3
- import { Config } from './config';
4
- export declare class FileManager {
5
- private ctx;
6
- private config;
7
- private dataFilePath;
8
- private fileOperationLock;
9
- private logger;
10
- private utils;
11
- constructor(ctx: Context, config: Config);
12
- private ensureDataDir;
13
- readChatDataFromFile(): ChatData;
14
- writeChatDataToFile(data: ChatData): void;
15
- cleanExcessMessages(data: ChatData): ChatData;
16
- addMessageToFile(messageInfo: MessageInfo): Promise<void>;
17
- private logInfo;
18
- }
package/lib/index.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import { Context } from 'koishi';
2
- import { Config } from './config';
3
- export declare const name = "chat-patch";
4
- export declare const reusable = false;
5
- export declare const filter = false;
6
- export declare const inject: {
7
- required: string[];
8
- };
9
- export declare const usage = "\n\n---\n\n\u5F00\u542F\u540E\uFF0C\u5373\u53EF\u5728koishi\u63A7\u5236\u53F0\u64CD\u4F5C\u673A\u5668\u4EBA\u6536\u53D1\u6D88\u606F\u5566\n\n\u6682\u65F6\u53EA\u652F\u6301\u63A5\u53D7\u56FE\u6587\u6D88\u606F / \u53D1\u9001\u6587\u5B57\u6D88\u606F\n\n---\n";
10
- export { Config } from './config';
11
- export declare function apply(ctx: Context, config: Config): Promise<void>;
@@ -1,16 +0,0 @@
1
- import { Context, Session } from 'koishi';
2
- import { Config } from './config';
3
- import { FileManager } from './file-manager';
4
- export declare class MessageHandler {
5
- private ctx;
6
- private config;
7
- private fileManager;
8
- private logger;
9
- private utils;
10
- constructor(ctx: Context, config: Config, fileManager: FileManager);
11
- updateBotInfoToFile(session: Session): Promise<void>;
12
- updateChannelInfoToFile(session: Session): Promise<string>;
13
- broadcastMessageEvent(session: Session): Promise<void>;
14
- broadcastBotMessageEvent(session: Session): Promise<void>;
15
- private logInfo;
16
- }
package/lib/types.d.ts DELETED
@@ -1,53 +0,0 @@
1
- import { h } from 'koishi';
2
- export interface BotInfo {
3
- selfId: string;
4
- platform: string;
5
- username: string;
6
- avatar?: string;
7
- status: 'online' | 'offline';
8
- }
9
- export interface ChannelInfo {
10
- id: string;
11
- name: string;
12
- type: number | string;
13
- guildId?: string;
14
- guildName?: string;
15
- }
16
- export interface QuoteInfo {
17
- messageId: string;
18
- id: string;
19
- content: string;
20
- elements?: h[];
21
- user: {
22
- id: string;
23
- name: string;
24
- userId: string;
25
- avatar?: string;
26
- username: string;
27
- };
28
- timestamp: number;
29
- }
30
- export interface MessageInfo {
31
- id: string;
32
- content: string;
33
- userId: string;
34
- username: string;
35
- avatar?: string;
36
- timestamp: number;
37
- channelId: string;
38
- selfId: string;
39
- elements?: h[];
40
- type: 'user' | 'bot';
41
- guildId?: string;
42
- guildName?: string;
43
- platform: string;
44
- quote?: QuoteInfo;
45
- }
46
- export interface ChatData {
47
- bots: Record<string, BotInfo>;
48
- channels: Record<string, Record<string, ChannelInfo>>;
49
- messages: Record<string, MessageInfo[]>;
50
- pinnedBots: string[];
51
- pinnedChannels: string[];
52
- lastSaveTime?: number;
53
- }
package/lib/utils.d.ts DELETED
@@ -1,9 +0,0 @@
1
- import { Config } from './config';
2
- export declare class Utils {
3
- private config;
4
- constructor(config: Config);
5
- isPlatformBlocked(platform: string): boolean;
6
- extractTextContent(elements: any[]): string;
7
- private isBase64;
8
- cleanBase64Content(obj: any): any;
9
- }