From 22204bedec29466a447bec47e64af2f98e09c0d4 Mon Sep 17 00:00:00 2001 From: hrx <18603305412@163.com> Date: Mon, 27 Apr 2026 10:27:48 +0800 Subject: [PATCH] updata --- .../homePage/components/topBox/index.vue | 103 +++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/f/web-kboss/src/views/homePage/components/topBox/index.vue b/f/web-kboss/src/views/homePage/components/topBox/index.vue index ee7f21a..0ab83fb 100644 --- a/f/web-kboss/src/views/homePage/components/topBox/index.vue +++ b/f/web-kboss/src/views/homePage/components/topBox/index.vue @@ -160,8 +160,13 @@ -
-
+
+
有问题,找开元 @@ -260,6 +265,15 @@ export default Vue.extend({ aiInput: '', aiLoading: false, aiMessages: [], + aiPanelPosition: { + left: null, + top: null + }, + aiPanelDragging: false, + aiPanelDragOffset: { + x: 0, + y: 0 + }, aiQuickQuestions: [ '推荐适合训练大模型的 GPU 服务器', '4090 和 A100 怎么选', @@ -308,6 +322,9 @@ export default Vue.extend({ } }); }, + beforeDestroy() { + this.stopAIPanelDrag() + }, computed: { ...mapGetters(["sidebar", "avatar", "device"]), ...mapState({ @@ -342,6 +359,18 @@ export default Vue.extend({ } else { return this.$route.path.includes('/homePage/index'); } + }, + aiPanelStyle() { + if (this.aiPanelPosition.left === null || this.aiPanelPosition.top === null) { + return {} + } + + return { + left: `${this.aiPanelPosition.left}px`, + top: `${this.aiPanelPosition.top}px`, + right: 'auto', + bottom: 'auto' + } } }, methods: { @@ -350,12 +379,14 @@ export default Vue.extend({ handleAIClick() { this.aiDialogVisible = true this.$nextTick(() => { + this.initAIPanelPosition() this.scrollAIChatToBottom() }) }, closeAIPanel() { this.aiDialogVisible = false + this.stopAIPanelDrag() }, resetAIChat() { @@ -367,6 +398,73 @@ export default Vue.extend({ this.sendAIMessage(question) }, + initAIPanelPosition() { + if (this.aiPanelPosition.left !== null && this.aiPanelPosition.top !== null) { + return + } + + const panel = this.$refs.aiChatPanel + if (!panel) return + + const panelWidth = panel.offsetWidth || 380 + const panelHeight = panel.offsetHeight || 620 + + this.aiPanelPosition = { + left: Math.max(window.innerWidth - panelWidth - 24, 16), + top: Math.max(window.innerHeight - panelHeight - 24, 16) + } + }, + + startAIPanelDrag(event) { + if (event.button !== 0) return + if (event.target && event.target.closest('.ai-chat-panel__close')) { + return + } + + const panel = this.$refs.aiChatPanel + if (!panel) return + + const rect = panel.getBoundingClientRect() + this.aiPanelDragging = true + this.aiPanelDragOffset = { + x: event.clientX - rect.left, + y: event.clientY - rect.top + } + + window.addEventListener('mousemove', this.handleAIPanelDrag) + window.addEventListener('mouseup', this.stopAIPanelDrag) + document.body.style.userSelect = 'none' + }, + + handleAIPanelDrag(event) { + if (!this.aiPanelDragging) return + + const panel = this.$refs.aiChatPanel + if (!panel) return + + const panelWidth = panel.offsetWidth || 380 + const panelHeight = panel.offsetHeight || 620 + const minLeft = 0 + const minTop = 0 + const maxLeft = Math.max(window.innerWidth - panelWidth, 0) + const maxTop = Math.max(window.innerHeight - panelHeight, 0) + + const nextLeft = event.clientX - this.aiPanelDragOffset.x + const nextTop = event.clientY - this.aiPanelDragOffset.y + + this.aiPanelPosition = { + left: Math.min(Math.max(nextLeft, minLeft), maxLeft), + top: Math.min(Math.max(nextTop, minTop), maxTop) + } + }, + + stopAIPanelDrag() { + this.aiPanelDragging = false + window.removeEventListener('mousemove', this.handleAIPanelDrag) + window.removeEventListener('mouseup', this.stopAIPanelDrag) + document.body.style.userSelect = '' + }, + handleAIKeydown(event) { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault() @@ -1251,6 +1349,7 @@ export default Vue.extend({ justify-content: space-between; border-bottom: 1px solid #f0f0f0; background: #fff; + cursor: move; } &__title {