fix: 前端页面架构重构初版
This commit is contained in:
226
Yi.Ai.Vue3/src/pages/chat/components/ConversationList.vue
Normal file
226
Yi.Ai.Vue3/src/pages/chat/components/ConversationList.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { useSessionStore } from '@/stores';
|
||||
|
||||
const router = useRouter();
|
||||
const sessionStore = useSessionStore();
|
||||
|
||||
// 会话列表加载状态
|
||||
const loading = computed(() => sessionStore.isLoading);
|
||||
const sessionList = computed(() => sessionStore.sessionList);
|
||||
|
||||
// 新建对话
|
||||
function handleNewChat() {
|
||||
router.push('/chat/conversation');
|
||||
}
|
||||
|
||||
// 选择对话
|
||||
function handleSelectSession(sessionId: string) {
|
||||
router.push(`/chat/conversation/${sessionId}`);
|
||||
}
|
||||
|
||||
// 删除对话
|
||||
async function handleDeleteSession(sessionId: string, sessionTitle: string) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除对话"${sessionTitle}"吗?`,
|
||||
'删除确认',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
},
|
||||
);
|
||||
|
||||
await sessionStore.deleteSessions([sessionId]);
|
||||
ElMessage.success('删除成功');
|
||||
|
||||
// 如果删除的是当前对话,跳转到新建页面
|
||||
if (router.currentRoute.value.params.id === sessionId) {
|
||||
router.push('/chat/conversation');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('删除失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 重命名对话
|
||||
async function handleRenameSession(sessionId: string, oldTitle: string) {
|
||||
try {
|
||||
const { value: newTitle } = await ElMessageBox.prompt('请输入新的对话名称', '重命名对话', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputValue: oldTitle,
|
||||
inputPattern: /\S+/,
|
||||
inputErrorMessage: '对话名称不能为空',
|
||||
});
|
||||
|
||||
if (newTitle && newTitle !== oldTitle) {
|
||||
await sessionStore.updateSession({
|
||||
id: sessionId,
|
||||
title: newTitle,
|
||||
});
|
||||
ElMessage.success('重命名成功');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
ElMessage.error('重命名失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多
|
||||
function handleLoadMore() {
|
||||
sessionStore.loadMoreSessions();
|
||||
}
|
||||
|
||||
// 初始化加载
|
||||
onMounted(() => {
|
||||
if (sessionList.value.length === 0) {
|
||||
sessionStore.requestSessionList();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="conversation-list">
|
||||
<!-- 新建对话按钮 -->
|
||||
<div class="new-chat-btn">
|
||||
<el-button type="primary" size="large" style="width: 100%;" @click="handleNewChat">
|
||||
<el-icon><i-ep-plus /></el-icon>
|
||||
新建对话
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 对话列表 -->
|
||||
<div v-loading="loading" class="session-list">
|
||||
<div
|
||||
v-for="session in sessionList"
|
||||
:key="session.id"
|
||||
class="session-item"
|
||||
:class="{ active: $route.params.id === session.id }"
|
||||
@click="handleSelectSession(session.id)"
|
||||
>
|
||||
<div class="session-content">
|
||||
<div class="session-title">
|
||||
{{ session.title || '未命名对话' }}
|
||||
</div>
|
||||
<div class="session-time">
|
||||
{{ session.updateTime || session.createTime }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="session-actions">
|
||||
<el-dropdown trigger="click" @command="(cmd: string) => cmd === 'delete' ? handleDeleteSession(session.id, session.title) : handleRenameSession(session.id, session.title)">
|
||||
<el-button size="small" text circle @click.stop>
|
||||
<el-icon><i-ep-more-filled /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="rename">
|
||||
<el-icon><i-ep-edit /></el-icon>
|
||||
重命名
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete">
|
||||
<el-icon><i-ep-delete /></el-icon>
|
||||
删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<div v-if="sessionStore.hasMore" class="load-more">
|
||||
<el-button text @click="handleLoadMore">
|
||||
加载更多
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<el-empty v-if="!loading && sessionList.length === 0" description="暂无对话记录" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.conversation-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 260px;
|
||||
border-right: 1px solid var(--el-border-color);
|
||||
background-color: var(--el-bg-color);
|
||||
}
|
||||
|
||||
.new-chat-btn {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
.session-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.session-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px;
|
||||
margin-bottom: 4px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
border-left: 3px solid var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.session-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.session-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--el-text-color-primary);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.session-time {
|
||||
font-size: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.session-actions {
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
.session-item:hover & {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.load-more {
|
||||
text-align: center;
|
||||
padding: 12px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user