koishi-plugin-chat-patch 1.0.11 → 1.0.13
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.
- package/client/vue/index.vue +48 -17
- package/client/vue/style.css +362 -326
- package/dist/index.js +3 -3
- package/dist/style.css +1 -1
- package/lib/index.js +1 -1
- package/package.json +1 -1
- package/src/config.ts +1 -1
- package/lib/api-handlers.d.ts +0 -17
- package/lib/file-manager.d.ts +0 -18
- package/lib/index.d.ts +0 -11
- package/lib/message-handler.d.ts +0 -16
package/client/vue/index.vue
CHANGED
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
</div>
|
|
165
165
|
|
|
166
166
|
<input v-model="inputMessage" type="text" :placeholder="inputPlaceholder" @keyup.enter="sendMessage"
|
|
167
|
-
:disabled="!canInputMessage" ref="messageInput" @paste="handlePaste" />
|
|
167
|
+
:disabled="!canInputMessage" ref="messageInput" @paste="handlePaste" @focus="handleInputFocus" />
|
|
168
168
|
<button @click="sendMessage" :disabled="!canSendMessage" :class="{ 'is-sending': isSending }">
|
|
169
169
|
{{ isSending ? '发送中...' : '发送' }}
|
|
170
170
|
</button>
|
|
@@ -445,7 +445,7 @@ const ImageComponent = defineComponent({
|
|
|
445
445
|
ref: imgRef,
|
|
446
446
|
draggable: false,
|
|
447
447
|
style: {
|
|
448
|
-
'max-width': '400px',
|
|
448
|
+
'max-width': 'min(400px, 66.67vw)',
|
|
449
449
|
'max-height': '200px',
|
|
450
450
|
'width': 'auto',
|
|
451
451
|
'height': 'auto',
|
|
@@ -1102,15 +1102,9 @@ const inputPlaceholder = computed(() => {
|
|
|
1102
1102
|
}
|
|
1103
1103
|
})
|
|
1104
1104
|
|
|
1105
|
+
// 简化的容器样式,现在主要由CSS处理
|
|
1105
1106
|
const chatContainerStyle = computed(() => {
|
|
1106
|
-
|
|
1107
|
-
const height = pluginConfig.value.chatContainerHeight || 80; // 默认80
|
|
1108
|
-
const marginTop = 100 - height - 19; // 19vh 是输入框高度,100是总高度
|
|
1109
|
-
return {
|
|
1110
|
-
height: `${height}vh`,
|
|
1111
|
-
marginTop: `${marginTop}vh`
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1107
|
+
// 移除复杂的高度计算,让CSS的dvh单位自动处理
|
|
1114
1108
|
return {};
|
|
1115
1109
|
});
|
|
1116
1110
|
|
|
@@ -1546,11 +1540,11 @@ function checkScrollPosition() {
|
|
|
1546
1540
|
|
|
1547
1541
|
showScrollButton.value = shouldShowButton
|
|
1548
1542
|
|
|
1549
|
-
//
|
|
1543
|
+
// 检测是否在主动滚动(向上滚动查看历史消息)
|
|
1550
1544
|
if (!isAtBottom) {
|
|
1551
1545
|
isUserScrolling.value = true
|
|
1552
1546
|
} else {
|
|
1553
|
-
//
|
|
1547
|
+
// 滚动到底部时,重置滚动状态
|
|
1554
1548
|
isUserScrolling.value = false
|
|
1555
1549
|
}
|
|
1556
1550
|
}
|
|
@@ -2646,10 +2640,10 @@ function handleMessageEvent(messageEvent: any) {
|
|
|
2646
2640
|
// 更新频道消息数量缓存
|
|
2647
2641
|
channelMessageCounts.value[channelKey] = messages.length
|
|
2648
2642
|
|
|
2649
|
-
//
|
|
2643
|
+
// 在添加新消息前检查是否在底部附近
|
|
2650
2644
|
const wasNearBottom = isNearBottom()
|
|
2651
2645
|
|
|
2652
|
-
//
|
|
2646
|
+
// 基于添加消息前的位置状态来决定是否滚动
|
|
2653
2647
|
nextTick(() => {
|
|
2654
2648
|
// 再次等待,确保新消息的DOM已经渲染
|
|
2655
2649
|
setTimeout(() => {
|
|
@@ -2730,7 +2724,7 @@ function handleBotMessageSentEvent(sentEvent: any) {
|
|
|
2730
2724
|
// 更新频道消息数量缓存
|
|
2731
2725
|
channelMessageCounts.value[channelKey] = messages.length
|
|
2732
2726
|
|
|
2733
|
-
//
|
|
2727
|
+
// 在添加新消息前检查是否在底部附近
|
|
2734
2728
|
const wasNearBottom = isNearBottom()
|
|
2735
2729
|
|
|
2736
2730
|
// 智能滚动:基于添加消息前的位置状态来决定是否滚动
|
|
@@ -2839,10 +2833,9 @@ function handleBotMessageEvent(botMessageEvent: any) {
|
|
|
2839
2833
|
// 更新频道消息数量缓存
|
|
2840
2834
|
channelMessageCounts.value[channelKey] = messages.length
|
|
2841
2835
|
|
|
2842
|
-
//
|
|
2836
|
+
// 在添加新消息前检查是否在底部附近
|
|
2843
2837
|
const wasNearBottom = isNearBottom()
|
|
2844
2838
|
|
|
2845
|
-
// 智能滚动:基于添加消息前的位置状态来决定是否滚动
|
|
2846
2839
|
nextTick(() => {
|
|
2847
2840
|
// 再次等待,确保新消息的DOM已经渲染
|
|
2848
2841
|
setTimeout(() => {
|
|
@@ -3129,12 +3122,47 @@ function checkMobile() {
|
|
|
3129
3122
|
isMobile.value = window.innerWidth <= 768
|
|
3130
3123
|
}
|
|
3131
3124
|
|
|
3125
|
+
// 判断是否应该自动滚动
|
|
3126
|
+
function shouldAutoScroll(): boolean {
|
|
3127
|
+
// 如果没有主动滚动,或者已经在底部附近,则应该自动滚动
|
|
3128
|
+
return !isUserScrolling.value || isNearBottom()
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
// 简单的视口高度管理
|
|
3132
|
+
const handleViewportChange = () => {
|
|
3133
|
+
if (isMobile.value && messageHistory.value) {
|
|
3134
|
+
// 当视口变化时,确保消息区域滚动到底部
|
|
3135
|
+
nextTick(() => {
|
|
3136
|
+
if (shouldAutoScroll()) {
|
|
3137
|
+
scrollToBottom()
|
|
3138
|
+
}
|
|
3139
|
+
})
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
// 输入框焦点处理
|
|
3144
|
+
const handleInputFocus = () => {
|
|
3145
|
+
if (isMobile.value) {
|
|
3146
|
+
// 延迟滚动,等待键盘完全出现
|
|
3147
|
+
setTimeout(() => {
|
|
3148
|
+
if (messageHistory.value && shouldAutoScroll()) {
|
|
3149
|
+
scrollToBottom()
|
|
3150
|
+
}
|
|
3151
|
+
}, 300)
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3132
3155
|
// 生命周期
|
|
3133
3156
|
onMounted(async () => {
|
|
3134
3157
|
// 检测手机端
|
|
3135
3158
|
checkMobile()
|
|
3136
3159
|
window.addEventListener('resize', checkMobile)
|
|
3137
3160
|
|
|
3161
|
+
// 添加视口变化监听(处理键盘弹出)
|
|
3162
|
+
if (window.visualViewport) {
|
|
3163
|
+
window.visualViewport.addEventListener('resize', handleViewportChange)
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3138
3166
|
// 添加点击外部关闭菜单的监听器
|
|
3139
3167
|
document.addEventListener('click', handleClickOutside)
|
|
3140
3168
|
|
|
@@ -3192,6 +3220,9 @@ onMounted(async () => {
|
|
|
3192
3220
|
// 在组件卸载时清理监听器
|
|
3193
3221
|
onUnmounted(() => {
|
|
3194
3222
|
window.removeEventListener('resize', checkMobile)
|
|
3223
|
+
if (window.visualViewport) {
|
|
3224
|
+
window.visualViewport.removeEventListener('resize', handleViewportChange)
|
|
3225
|
+
}
|
|
3195
3226
|
document.removeEventListener('click', handleClickOutside)
|
|
3196
3227
|
|
|
3197
3228
|
if (dispose1 && typeof dispose1 === 'function') {
|