【代码优化】AI:对话 deleteChatConversationMyByUnpinned 接口

pull/471/head^2
YunaiV 2024-07-04 23:40:03 +08:00
parent cabfc5ccc0
commit c09af1cbe1
8 changed files with 55 additions and 62 deletions

View File

@ -43,8 +43,8 @@ export const ChatConversationApi = {
},
// 删除【我的】所有对话,置顶除外
deleteMyAllExceptPinned: async () => {
return await request.delete({ url: `/ai/chat/conversation/delete-my-all-except-pinned` })
deleteChatConversationMyByUnpinned: async () => {
return await request.delete({ url: `/ai/chat/conversation/delete-by-unpinned` })
},
// 获得【我的】聊天对话列表

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 121 KiB

View File

@ -29,7 +29,7 @@ const download = {
html: (data: Blob, fileName: string) => {
download0(data, fileName, 'text/html')
},
// 下载 MarkdownView 方法
// 下载 Markdown 方法
markdown: (data: Blob, fileName: string) => {
download0(data, fileName, 'text/markdown')
}

View File

@ -1,11 +1,10 @@
<!-- AI 对话 -->
<template>
<el-aside width="260px" class="conversation-container" style="height: 100%;">
<el-aside width="260px" class="conversation-container" style="height: 100%">
<!-- 左顶部对话 -->
<div style="height: 100%;">
<div style="height: 100%">
<el-button class="w-1/1 btn-new-conversation" type="primary" @click="createConversation">
<Icon icon="ep:plus" class="mr-5px"/>
<Icon icon="ep:plus" class="mr-5px" />
新建对话
</el-button>
@ -18,17 +17,19 @@
@keyup="searchConversation"
>
<template #prefix>
<Icon icon="ep:search"/>
<Icon icon="ep:search" />
</template>
</el-input>
<!-- 左中间对话列表 -->
<div class="conversation-list">
<el-empty v-if="loading" description="." :v-loading="loading" />
<div v-for="conversationKey in Object.keys(conversationMap)" :key="conversationKey">
<div class="conversation-item classify-title" v-if="conversationMap[conversationKey].length">
<div
class="conversation-item classify-title"
v-if="conversationMap[conversationKey].length"
>
<el-text class="mx-1" size="small" tag="b">{{ conversationKey }}</el-text>
</div>
<div
@ -40,25 +41,27 @@
@mouseout="hoverConversationId = ''"
>
<div
:class="conversation.id === activeConversationId ? 'conversation active' : 'conversation'"
:class="
conversation.id === activeConversationId ? 'conversation active' : 'conversation'
"
>
<div class="title-wrapper">
<img class="avatar" :src="conversation.roleAvatar || roleAvatarDefaultImg"/>
<img class="avatar" :src="conversation.roleAvatar || roleAvatarDefaultImg" />
<span class="title">{{ conversation.title }}</span>
</div>
<div class="button-wrapper" v-show="hoverConversationId === conversation.id">
<el-button class="btn" link @click.stop="handlerTop(conversation)" >
<el-button class="btn" link @click.stop="handlerTop(conversation)">
<el-icon title="置顶" v-if="!conversation.pinned"><Top /></el-icon>
<el-icon title="置顶" v-if="conversation.pinned"><Bottom /></el-icon>
</el-button>
<el-button class="btn" link @click.stop="updateConversationTitle(conversation)">
<el-icon title="编辑" >
<Icon icon="ep:edit"/>
<el-icon title="编辑">
<Icon icon="ep:edit" />
</el-icon>
</el-button>
<el-button class="btn" link @click.stop="deleteChatConversation(conversation)">
<el-icon title="删除对话" >
<Icon icon="ep:delete"/>
<el-icon title="删除对话">
<Icon icon="ep:delete" />
</el-icon>
</el-button>
</div>
@ -66,20 +69,19 @@
</div>
</div>
<!-- 底部站位 -->
<div style="height: 160px; width: 100%;"></div>
<div style="height: 160px; width: 100%"></div>
</div>
</div>
<!-- 左底部工具栏 -->
<!-- TODO @fan下面两个 icon可以使用类似 <Icon icon="ep:question-filled" /> 替代哈 -->
<div class="tool-box">
<div @click="handleRoleRepository">
<Icon icon="ep:user"/>
<Icon icon="ep:user" />
<el-text size="small">角色仓库</el-text>
</div>
<div @click="handleClearConversation">
<Icon icon="ep:delete"/>
<Icon icon="ep:delete" />
<el-text size="small">清空未置顶对话</el-text>
</div>
</div>
@ -88,17 +90,16 @@
<!-- 角色仓库抽屉 -->
<el-drawer v-model="drawer" title="角色仓库" size="754px">
<Role/>
<Role />
</el-drawer>
</el-aside>
</template>
<script setup lang="ts">
import {ChatConversationApi, ChatConversationVO} from '@/api/ai/chat/conversation'
import {ref} from "vue";
import Role from "@/views/ai/chat/role/index.vue";
import {Bottom, Top} from "@element-plus/icons-vue";
import { ChatConversationApi, ChatConversationVO } from '@/api/ai/chat/conversation'
import { ref } from 'vue'
import Role from '@/views/ai/chat/role/index.vue'
import { Bottom, Top } from '@element-plus/icons-vue'
import roleAvatarDefaultImg from '@/assets/ai/gpt.svg'
const message = useMessage() //
@ -107,8 +108,8 @@ const message = useMessage() // 消息弹窗
const searchName = ref<string>('') //
const activeConversationId = ref<string | null>(null) // null
const hoverConversationId = ref<string | null>(null) //
const conversationList = ref([] as ChatConversationVO[]) //
const conversationMap = ref<any>({}) // ()
const conversationList = ref([] as ChatConversationVO[]) //
const conversationMap = ref<any>({}) // ()
const drawer = ref<boolean>(false) // TODO @fanroleDrawer
const loading = ref<boolean>(false) //
const loadingTime = ref<any>() //
@ -138,7 +139,7 @@ const searchConversation = async (e) => {
conversationMap.value = await conversationTimeGroup(conversationList.value)
} else {
//
const filterValues = conversationList.value.filter(item => {
const filterValues = conversationList.value.filter((item) => {
return item.title.includes(searchName.value.trim())
})
conversationMap.value = await conversationTimeGroup(filterValues)
@ -150,7 +151,7 @@ const searchConversation = async (e) => {
*/
const handleConversationClick = async (id: string) => {
//
const filterConversation = conversationList.value.filter(item => {
const filterConversation = conversationList.value.filter((item) => {
return item.id === id
})
// onConversationClick
@ -211,20 +212,20 @@ const getChatConversationList = async () => {
const conversationTimeGroup = async (list: ChatConversationVO[]) => {
// (30)
const groupMap = {
'置顶': [],
'今天': [],
'一天前': [],
'三天前': [],
'七天前': [],
'三十天前': []
置顶: [],
今天: [],
一天前: [],
三天前: [],
七天前: [],
三十天前: []
}
//
const now = Date.now();
const now = Date.now()
//
const oneDay = 24 * 60 * 60 * 1000;
const threeDays = 3 * oneDay;
const sevenDays = 7 * oneDay;
const thirtyDays = 30 * oneDay;
const oneDay = 24 * 60 * 60 * 1000
const threeDays = 3 * oneDay
const sevenDays = 7 * oneDay
const thirtyDays = 30 * oneDay
for (const conversation: ChatConversationVO of list) {
//
if (conversation.pinned) {
@ -232,7 +233,7 @@ const conversationTimeGroup = async (list: ChatConversationVO[]) => {
continue
}
//
const diff = now - conversation.updateTime;
const diff = now - conversation.updateTime
//
if (diff < oneDay) {
groupMap['今天'].push(conversation)
@ -271,7 +272,7 @@ const createConversation = async () => {
*/
const updateConversationTitle = async (conversation: ChatConversationVO) => {
// 1.
const {value} = await ElMessageBox.prompt('修改标题', {
const { value } = await ElMessageBox.prompt('修改标题', {
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, //
inputErrorMessage: '标题不能为空',
inputValue: conversation.title
@ -285,7 +286,7 @@ const updateConversationTitle = async (conversation: ChatConversationVO) => {
// 3.
await getChatConversationList()
// 4.
const filterConversationList = conversationList.value.filter(item => {
const filterConversationList = conversationList.value.filter((item) => {
return item.id === conversation.id
})
if (filterConversationList.length > 0) {
@ -310,8 +311,7 @@ const deleteChatConversation = async (conversation: ChatConversationVO) => {
await getChatConversationList()
//
emits('onConversationDelete', conversation)
} catch {
}
} catch {}
}
/**
@ -343,16 +343,13 @@ const handleRoleRepository = async () => {
*/
const handleClearConversation = async () => {
// TODO @fan使 await message.confirm( 使 await
ElMessageBox.confirm(
'确认后对话会全部清空,置顶的对话除外。',
'确认提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
ElMessageBox.confirm('确认后对话会全部清空,置顶的对话除外。', '确认提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
await ChatConversationApi.deleteMyAllExceptPinned()
await ChatConversationApi.deleteChatConversationMyByUnpinned()
ElMessage({
message: '操作成功!',
type: 'success'
@ -364,8 +361,7 @@ const handleClearConversation = async () => {
//
emits('onConversationClear')
})
.catch(() => {
})
.catch(() => {})
}
// ============ onMounted
@ -377,7 +373,7 @@ watch(activeId, async (newValue, oldValue) => {
})
// public
defineExpose({createConversation})
defineExpose({ createConversation })
onMounted(async () => {
//
@ -394,11 +390,9 @@ onMounted(async () => {
}
}
})
</script>
<style scoped lang="scss">
.conversation-container {
position: relative;
display: flex;

1
types/env.d.ts vendored
View File

@ -19,7 +19,6 @@ interface ImportMetaEnv {
readonly VITE_UPLOAD_URL: string
readonly VITE_API_URL: string
readonly VITE_BASE_PATH: string
readonly VITE_STATIC_URL: string
readonly VITE_DROP_DEBUGGER: string
readonly VITE_DROP_CONSOLE: string
readonly VITE_SOURCEMAP: string