reactor:【AI 大模型】chat/message 简化成 unocss

pull/804/head
YunaiV 2025-07-27 20:59:04 +08:00
parent 9a16b2b34d
commit 9d5b8ff76a
3 changed files with 34 additions and 216 deletions

View File

@ -1,52 +1,52 @@
<template>
<div ref="messageContainer" class="h-100% overflow-y-auto relative">
<div class="chat-list" v-for="(item, index) in list" :key="index">
<div class="flex flex-col overflow-y-hidden px-20px" v-for="(item, index) in list" :key="index">
<!-- 靠左 messagesystemassistant 类型 -->
<div class="left-message message-item" v-if="item.type !== 'user'">
<div class="flex flex-row mt-50px" v-if="item.type !== 'user'">
<div class="avatar">
<el-avatar :src="roleAvatar" />
</div>
<div class="message">
<div class="flex flex-col text-left mx-15px">
<div>
<el-text class="time">{{ formatDate(item.createTime) }}</el-text>
<el-text class="text-left leading-30px">{{ formatDate(item.createTime) }}</el-text>
</div>
<div class="left-text-container" ref="markdownViewRef">
<MarkdownView class="left-text" :content="item.content" />
<div class="relative flex flex-col break-words bg-[var(--el-fill-color-light)] shadow-[0_0_0_1px_var(--el-border-color-light)] rounded-10px pt-10px px-10px pb-5px" ref="markdownViewRef">
<MarkdownView class="text-[var(--el-text-color-primary)] text-[0.95rem]" :content="item.content" />
<MessageKnowledge v-if="item.segments" :segments="item.segments" />
</div>
<div class="left-btns">
<el-button class="btn-cus" link @click="copyContent(item.content)">
<img class="btn-image" src="@/assets/ai/copy.svg" />
<div class="flex flex-row mt-8px">
<el-button class="flex bg-transparent items-center hover:cursor-pointer hover:bg-[var(--el-fill-color-lighter)]" link @click="copyContent(item.content)">
<img class="h-20px" src="@/assets/ai/copy.svg" />
</el-button>
<el-button v-if="item.id > 0" class="btn-cus" link @click="onDelete(item.id)">
<img class="btn-image h-17px" src="@/assets/ai/delete.svg" />
<el-button v-if="item.id > 0" class="flex bg-transparent items-center hover:cursor-pointer hover:bg-[var(--el-fill-color-lighter)]" link @click="onDelete(item.id)">
<img class="h-17px" src="@/assets/ai/delete.svg" />
</el-button>
</div>
</div>
</div>
<!-- 靠右 messageuser 类型 -->
<div class="right-message message-item" v-if="item.type === 'user'">
<div class="flex flex-row-reverse justify-start mt-50px" v-if="item.type === 'user'">
<div class="avatar">
<el-avatar :src="userAvatar" />
</div>
<div class="message">
<div class="flex flex-col text-left mx-15px">
<div>
<el-text class="time">{{ formatDate(item.createTime) }}</el-text>
<el-text class="text-left leading-30px">{{ formatDate(item.createTime) }}</el-text>
</div>
<div class="right-text-container">
<div class="right-text">{{ item.content }}</div>
<div class="flex flex-row-reverse">
<div class="text-[0.95rem] text-[var(--el-color-white)] inline bg-[var(--el-color-primary)] shadow-[0_0_0_1px_var(--el-color-primary)] rounded-10px p-10px w-auto break-words whitespace-pre-wrap">{{ item.content }}</div>
</div>
<div class="right-btns">
<el-button class="btn-cus" link @click="copyContent(item.content)">
<img class="btn-image" src="@/assets/ai/copy.svg" />
<div class="flex flex-row-reverse mt-8px">
<el-button class="flex bg-transparent items-center hover:cursor-pointer hover:bg-[var(--el-fill-color-lighter)]" link @click="copyContent(item.content)">
<img class="h-20px" src="@/assets/ai/copy.svg" />
</el-button>
<el-button class="btn-cus" link @click="onDelete(item.id)">
<img class="btn-image h-17px mr-12px" src="@/assets/ai/delete.svg" />
<el-button class="flex bg-transparent items-center hover:cursor-pointer hover:bg-[var(--el-fill-color-lighter)]" link @click="onDelete(item.id)">
<img class="h-17px mr-12px" src="@/assets/ai/delete.svg" />
</el-button>
<el-button class="btn-cus" link @click="onRefresh(item)">
<el-button class="flex bg-transparent items-center hover:cursor-pointer hover:bg-[var(--el-fill-color-lighter)]" link @click="onRefresh(item)">
<el-icon size="17"><RefreshRight /></el-icon>
</el-button>
<el-button class="btn-cus" link @click="onEdit(item)">
<el-button class="flex bg-transparent items-center hover:cursor-pointer hover:bg-[var(--el-fill-color-lighter)]" link @click="onEdit(item)">
<el-icon size="17"><Edit /></el-icon>
</el-button>
</div>
@ -55,7 +55,7 @@
</div>
</div>
<!-- 回到底部 -->
<div v-if="isScrolling" class="to-bottom" @click="handleGoBottom">
<div v-if="isScrolling" class="absolute z-1000 bottom-0 right-50%" @click="handleGoBottom">
<el-button :icon="ArrowDownBold" circle />
</div>
</template>
@ -142,7 +142,7 @@ defineExpose({ scrollToBottom, handlerGoTop }) // 提供方法给 parent 调用
// ============ ==============
/** 复制 */
const copyContent = async (content) => {
const copyContent = async (content: string) => {
await copy(content)
message.success('复制成功!')
}
@ -172,113 +172,4 @@ onMounted(async () => {
})
</script>
<style scoped lang="scss">
.message-container {
position: relative;
overflow-y: scroll;
}
//
.chat-list {
display: flex;
flex-direction: column;
overflow-y: hidden;
padding: 0 20px;
.message-item {
margin-top: 50px;
}
.left-message {
display: flex;
flex-direction: row;
}
.right-message {
display: flex;
flex-direction: row-reverse;
justify-content: flex-start;
}
.message {
display: flex;
flex-direction: column;
text-align: left;
margin: 0 15px;
.time {
text-align: left;
line-height: 30px;
}
.left-text-container {
position: relative;
display: flex;
flex-direction: column;
overflow-wrap: break-word;
background-color: var(--el-fill-color-light);
box-shadow: 0 0 0 1px var(--el-border-color-light);
border-radius: 10px;
padding: 10px 10px 5px 10px;
.left-text {
color: var(--el-text-color-primary);
font-size: 0.95rem;
}
}
.right-text-container {
display: flex;
flex-direction: row-reverse;
.right-text {
font-size: 0.95rem;
color: var(--el-color-white);
display: inline;
background-color: var(--el-color-primary);
box-shadow: 0 0 0 1px var(--el-color-primary);
border-radius: 10px;
padding: 10px;
width: auto;
overflow-wrap: break-word;
white-space: pre-wrap;
}
}
.left-btns {
display: flex;
flex-direction: row;
margin-top: 8px;
}
.right-btns {
display: flex;
flex-direction: row-reverse;
margin-top: 8px;
}
}
//
.btn-cus {
display: flex;
background-color: transparent;
align-items: center;
.btn-image {
height: 20px;
}
}
.btn-cus:hover {
cursor: pointer;
background-color: var(--el-fill-color-lighter);
}
}
//
.to-bottom {
position: absolute;
z-index: 1000;
bottom: 0;
right: 50%;
}
</style>

View File

@ -1,12 +1,12 @@
<!-- 消息列表为空时展示 prompt 列表 -->
<template>
<div class="chat-empty">
<div class="relative flex flex-row justify-center w-full h-full">
<!-- title -->
<div class="center-container">
<div class="title">芋道 AI</div>
<div class="role-list">
<div class="flex flex-col justify-center">
<div class="text-28px font-bold text-center">芋道 AI</div>
<div class="flex flex-row flex-wrap items-center justify-center w-460px mt-20px">
<div
class="role-item"
class="flex justify-center w-180px leading-50px border border-solid border-[#e4e4e4] rounded-10px m-10px cursor-pointer hover:bg-[rgba(243,243,243,0.73)]"
v-for="prompt in promptList"
:key="prompt.prompt"
@click="handlerPromptClick(prompt)"
@ -34,50 +34,3 @@ const handlerPromptClick = async ({ prompt }) => {
emits('onPrompt', prompt)
}
</script>
<style scoped lang="scss">
.chat-empty {
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
width: 100%;
height: 100%;
.center-container {
display: flex;
flex-direction: column;
justify-content: center;
.title {
font-size: 28px;
font-weight: bold;
text-align: center;
}
.role-list {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: center;
width: 460px;
margin-top: 20px;
.role-item {
display: flex;
justify-content: center;
width: 180px;
line-height: 50px;
border: 1px solid #e4e4e4;
border-radius: 10px;
margin: 10px;
cursor: pointer;
}
.role-item:hover {
background-color: rgba(243, 243, 243, 0.73);
}
}
}
}
</style>

View File

@ -1,9 +1,9 @@
<!-- 无聊天对话时 message 区域可以新增对话 -->
<template>
<div class="new-chat">
<div class="box-center">
<div class="tip">点击下方按钮开始你的对话吧</div>
<div class="btns">
<div class="flex flex-row justify-center w-100% h-100%">
<div class="flex flex-col justify-center">
<div class="text-14px text-#858585">点击下方按钮开始你的对话吧</div>
<div class="flex flex-row justify-center mt-20px">
<el-button type="primary" round @click="handlerNewChat"></el-button>
</div>
</div>
@ -17,30 +17,4 @@ const handlerNewChat = () => {
emits('onNewConversation')
}
</script>
<style scoped lang="scss">
.new-chat {
display: flex;
flex-direction: row;
justify-content: center;
width: 100%;
height: 100%;
.box-center {
display: flex;
flex-direction: column;
justify-content: center;
.tip {
font-size: 14px;
color: #858585;
}
.btns {
display: flex;
flex-direction: row;
justify-content: center;
margin-top: 20px;
}
}
}
</style>