feat: 搭建聊天的页面

This commit is contained in:
zoujing
2026-01-13 16:04:15 +08:00
parent 97d181af8a
commit 521d96b673
4 changed files with 90 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
<template>
<main class="bg-white box-border w-full h-screen flex pt-[8px] pb-[8px] pl-[8px] ">
<main class="bg-[#f7f9fc] box-border w-full h-screen flex pt-[8px] pb-[8px] pl-[8px] ">
<div class="flex-1 flex gap-[8px]">
<div class="flex-1 h-full">

View File

@@ -0,0 +1,80 @@
<template>
<!-- 页面根 -->
<div class="h-full overflow-hidden flex flex-col">
<!-- 消息列表唯一滚动区 -->
<div ref="listRef" class="flex-1 overflow-y-auto px-6 py-6 space-y-6">
<div v-for="msg in messages" :key="msg.id" class="flex items-start gap-3"
:class="msg.role === 'user' ? 'justify-end' : 'justify-start'">
<!-- AI avatar -->
<div v-if="msg.role === 'ai'"
class="w-9 h-9 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold shrink-0">
N
</div>
<!-- 气泡 -->
<div class="max-w-[70%]">
<div class="px-4 py-3 text-sm text-gray-700" :class="msg.role === 'user' ? 'bg-[#f7f9fc] rounded-md' : ''">
{{ msg.content }}
</div>
<!-- AI 标识 -->
<div v-if="msg.role === 'ai'" class="mt-1 text-xs text-gray-400 ">
本回答由 AI 生成
</div>
</div>
<!-- User avatar -->
<div v-if="msg.role === 'user'" class="w-9 h-9 rounded-full bg-blue-200 shrink-0"></div>
</div>
</div>
<!-- 输入区固定底部不滚 -->
<div class="shrink-0 px-6 py-4 gap-3">
<div class="inline-flex items-center justify-center w-[108px]
px-3 py-1.5 rounded-2xl border border-[#E5E8EE]
text-[13px] text-[#333]">
智能问数
</div>
<div class="h-[174px] bg-white rounded-lg border border-[#eef2f6]
shadow-[0_1px_0_rgba(0,0,0,0.03)]
p-[18px] mt-[8px] flex flex-col justify-between">
<textarea rows="2" placeholder="给我发布或者布置任务" class="flex-1 resize-none outline-none text-sm" />
<div class="flex justify-between items-center">
<button class="text-[#9fb0c4]">🔗</button>
<button class="bg-[#f1f6fb] px-2.5 py-1.5 rounded-md">
</button>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
type Message = {
id: number
role: 'user' | 'ai'
content: string
}
const messages = ref<Message[]>(
Array.from({ length: 40 }).map((_, i) => ({
id: i,
role: i % 2 === 0 ? 'user' : 'ai',
content:
i % 2 === 0
? '这里是一段用户输入的消息,用于测试滚动效果。'.repeat(
(i % 3) + 1
)
: '这里是一段 AI 回复的内容,用于测试长文本下的滚动体验。'.repeat(
(i % 4) + 1
),
}))
)
</script>

View File

@@ -15,7 +15,7 @@
<section v-for="group in groups" :key="group.title" class="mb-3">
<div class="flex items-center justify-between text-sm text-gray-500 py-2">
<span>{{ group.title }}</span>
<span class="text-gray-400 mr-4"></span>
<RiArrowDownSLine />
</div>
<ul class="list-none p-1 mr-4">
@@ -38,6 +38,7 @@
<script setup lang="ts">
import { ref } from 'vue'
import { RiArrowDownSLine } from '@remixicon/vue'
const selectedId = ref<number | null>(2)

View File

@@ -1,15 +1,17 @@
<template>
<div class="bg-white h-full w-full p-[20px]">
<div class="bg-[#f7f9fc] h-full w-full px-[20px]">
<div class="flex h-full w-full flex-col md:flex-row">
<message-list class="flex-none w-64" />
<div class="flex-1 overflow-auto p-5">
<chat-guide />
<chat-history class="flex-none w-64" />
<div class="flex-1 overflow-auto px-5 bg-white rounded-xl">
<!-- <chat-guide /> -->
<chat-box />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import MessageList from './MessageList.vue'
import ChatHistory from './ChatHistory.vue'
import ChatGuide from './ChatGuide.vue'
import ChatBox from './ChatBox.vue'
</script>