【代码优化】AI:聊天对话 index.vue 代码梳理 80%(message 部分)

pull/474/MERGE
YunaiV 2024-07-08 21:12:49 +08:00
parent 1a6afa3263
commit 6224602152
6 changed files with 137 additions and 185 deletions

View File

@ -1,8 +1,8 @@
<!-- AI 对话 --> <!-- AI 对话 -->
<template> <template>
<el-aside width="260px" class="conversation-container" style="height: 100%"> <el-aside width="260px" class="conversation-container h-100%">
<!-- 左顶部对话 --> <!-- 左顶部对话 -->
<div style="height: 100%"> <div class="h-100%">
<el-button class="w-1/1 btn-new-conversation" type="primary" @click="createConversation"> <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" />
新建对话 新建对话
@ -23,8 +23,9 @@
<!-- 左中间对话列表 --> <!-- 左中间对话列表 -->
<div class="conversation-list"> <div class="conversation-list">
<!-- 情况一加载中 -->
<el-empty v-if="loading" description="." :v-loading="loading" /> <el-empty v-if="loading" description="." :v-loading="loading" />
<!-- 情况二按照 group 分组展示聊天会话 list 列表 -->
<div v-for="conversationKey in Object.keys(conversationMap)" :key="conversationKey"> <div v-for="conversationKey in Object.keys(conversationMap)" :key="conversationKey">
<div <div
class="conversation-item classify-title" class="conversation-item classify-title"
@ -50,7 +51,7 @@
<span class="title">{{ conversation.title }}</span> <span class="title">{{ conversation.title }}</span>
</div> </div>
<div class="button-wrapper" v-show="hoverConversationId === conversation.id"> <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="handleTop(conversation)">
<el-icon title="置顶" v-if="!conversation.pinned"><Top /></el-icon> <el-icon title="置顶" v-if="!conversation.pinned"><Top /></el-icon>
<el-icon title="置顶" v-if="conversation.pinned"><Bottom /></el-icon> <el-icon title="置顶" v-if="conversation.pinned"><Bottom /></el-icon>
</el-button> </el-button>
@ -68,13 +69,12 @@
</div> </div>
</div> </div>
</div> </div>
<!-- 底部站--> <!-- 底部占-->
<div style="height: 160px; width: 100%"></div> <div class="h-160px w-100%"></div>
</div> </div>
</div> </div>
<!-- 左底部工具栏 --> <!-- 左底部工具栏 -->
<!-- TODO @fan下面两个 icon可以使用类似 <Icon icon="ep:question-filled" /> 替代哈 -->
<div class="tool-box"> <div class="tool-box">
<div @click="handleRoleRepository"> <div @click="handleRoleRepository">
<Icon icon="ep:user" /> <Icon icon="ep:user" />
@ -86,19 +86,16 @@
</div> </div>
</div> </div>
<!-- ============= 额外组件 ============= -->
<!-- 角色仓库抽屉 --> <!-- 角色仓库抽屉 -->
<el-drawer v-model="drawer" title="角色仓库" size="754px"> <el-drawer v-model="roleRepositoryOpen" title="角色仓库" size="754px">
<Role /> <RoleRepository />
</el-drawer> </el-drawer>
</el-aside> </el-aside>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ChatConversationApi, ChatConversationVO } from '@/api/ai/chat/conversation' import { ChatConversationApi, ChatConversationVO } from '@/api/ai/chat/conversation'
import { ref } from 'vue' import RoleRepository from '../role/RoleRepository.vue'
import Role from '../role/index.vue'
import { Bottom, Top } from '@element-plus/icons-vue' import { Bottom, Top } from '@element-plus/icons-vue'
import roleAvatarDefaultImg from '@/assets/ai/gpt.svg' import roleAvatarDefaultImg from '@/assets/ai/gpt.svg'
@ -106,11 +103,10 @@ const message = useMessage() // 消息弹窗
// //
const searchName = ref<string>('') // const searchName = ref<string>('') //
const activeConversationId = ref<string | null>(null) // null const activeConversationId = ref<number | null>(null) // null
const hoverConversationId = ref<string | null>(null) // const hoverConversationId = ref<number | null>(null) //
const conversationList = ref([] as ChatConversationVO[]) // const conversationList = ref([] as ChatConversationVO[]) //
const conversationMap = ref<any>({}) // () const conversationMap = ref<any>({}) // ()
const drawer = ref<boolean>(false) // TODO @fanroleDrawer
const loading = ref<boolean>(false) // const loading = ref<boolean>(false) //
const loadingTime = ref<any>() // const loadingTime = ref<any>() //
@ -130,75 +126,58 @@ const emits = defineEmits([
'onConversationDelete' 'onConversationDelete'
]) ])
/** /** 搜索对话 */
* 对话 - 搜索
*/
const searchConversation = async (e) => { const searchConversation = async (e) => {
// //
if (!searchName.value.trim().length) { if (!searchName.value.trim().length) {
conversationMap.value = await conversationTimeGroup(conversationList.value) conversationMap.value = await getConversationGroupByCreateTime(conversationList.value)
} else { } else {
// //
const filterValues = conversationList.value.filter((item) => { const filterValues = conversationList.value.filter((item) => {
return item.title.includes(searchName.value.trim()) return item.title.includes(searchName.value.trim())
}) })
conversationMap.value = await conversationTimeGroup(filterValues) conversationMap.value = await getConversationGroupByCreateTime(filterValues)
} }
} }
/** /** 点击对话 */
* 对话 - 点击 const handleConversationClick = async (id: number) => {
*/
const handleConversationClick = async (id: string) => {
// //
const filterConversation = conversationList.value.filter((item) => { const filterConversation = conversationList.value.filter((item) => {
return item.id === id return item.id === id
}) })
// onConversationClick // onConversationClick
// TODO @fan: idea // noinspection JSVoidFunctionReturnValueUsed
const res = emits('onConversationClick', filterConversation[0]) const success = emits('onConversationClick', filterConversation[0])
// //
if (res) { if (success) {
activeConversationId.value = id activeConversationId.value = id
} }
} }
/** /** 获取对话列表 */
* 对话 - 获取列表
*/
const getChatConversationList = async () => { const getChatConversationList = async () => {
try { try {
// 0. //
loadingTime.value = setTimeout(() => { loadingTime.value = setTimeout(() => {
loading.value = true loading.value = true
}, 50) }, 50)
// 1.
const res = await ChatConversationApi.getChatConversationMyList() // 1.1
// 2. conversationList.value = await ChatConversationApi.getChatConversationMyList()
res.sort((a, b) => { // 1.2
conversationList.value.sort((a, b) => {
return b.createTime - a.createTime return b.createTime - a.createTime
}) })
conversationList.value = res // 1.3
// 3.
if (!activeId?.value) {
// await handleConversationClick(res[0].id)
} else {
// tip:
// const filterConversationList = conversationList.value.filter(item => {
// return item.id === activeId.value
// })
// if (filterConversationList.length <= 0) {
// await handleConversationClick(res[0].id)
// }
}
// 4.
if (conversationList.value.length === 0) { if (conversationList.value.length === 0) {
activeConversationId.value = null activeConversationId.value = null
conversationMap.value = {} conversationMap.value = {}
return return
} }
// 5. (30)
conversationMap.value = await conversationTimeGroup(conversationList.value) // 2. (30 )
conversationMap.value = await getConversationGroupByCreateTime(conversationList.value)
} finally { } finally {
// //
if (loadingTime.value) { if (loadingTime.value) {
@ -209,8 +188,10 @@ const getChatConversationList = async () => {
} }
} }
const conversationTimeGroup = async (list: ChatConversationVO[]) => { /** 按照 creteTime 创建时间,进行分组 */
const getConversationGroupByCreateTime = async (list: ChatConversationVO[]) => {
// (30) // (30)
// noinspection NonAsciiCharacters
const groupMap = { const groupMap = {
置顶: [], 置顶: [],
今天: [], 今天: [],
@ -233,7 +214,7 @@ const conversationTimeGroup = async (list: ChatConversationVO[]) => {
continue continue
} }
// //
const diff = now - conversation.updateTime const diff = now - conversation.createTime
// //
if (diff < oneDay) { if (diff < oneDay) {
groupMap['今天'].push(conversation) groupMap['今天'].push(conversation)
@ -250,9 +231,7 @@ const conversationTimeGroup = async (list: ChatConversationVO[]) => {
return groupMap return groupMap
} }
/** /** 新建对话 */
* 对话 - 新建
*/
const createConversation = async () => { const createConversation = async () => {
// 1. // 1.
const conversationId = await ChatConversationApi.createChatConversationMy( const conversationId = await ChatConversationApi.createChatConversationMy(
@ -266,9 +245,7 @@ const createConversation = async () => {
emits('onConversationCreate') emits('onConversationCreate')
} }
/** /** 修改对话的标题 */
* 对话 - 更新标题
*/
const updateConversationTitle = async (conversation: ChatConversationVO) => { const updateConversationTitle = async (conversation: ChatConversationVO) => {
// 1. // 1.
const { value } = await ElMessageBox.prompt('修改标题', { const { value } = await ElMessageBox.prompt('修改标题', {
@ -296,9 +273,7 @@ const updateConversationTitle = async (conversation: ChatConversationVO) => {
} }
} }
/** /** 删除聊天对话 */
* 删除聊天对话
*/
const deleteChatConversation = async (conversation: ChatConversationVO) => { const deleteChatConversation = async (conversation: ChatConversationVO) => {
try { try {
// //
@ -313,11 +288,26 @@ const deleteChatConversation = async (conversation: ChatConversationVO) => {
} catch {} } catch {}
} }
/** /** 清空对话 */
* 对话置顶 const handleClearConversation = async () => {
*/ try {
// TODO @fan handleXXXhandler await message.confirm('确认后对话会全部清空,置顶的对话除外。')
const handlerTop = async (conversation: ChatConversationVO) => { await ChatConversationApi.deleteChatConversationMyByUnpinned()
ElMessage({
message: '操作成功!',
type: 'success'
})
//
activeConversationId.value = null
//
await getChatConversationList()
//
emits('onConversationClear')
} catch {}
}
/** 对话置顶 */
const handleTop = async (conversation: ChatConversationVO) => {
// //
conversation.pinned = !conversation.pinned conversation.pinned = !conversation.pinned
await ChatConversationApi.updateChatConversationMy(conversation) await ChatConversationApi.updateChatConversationMy(conversation)
@ -325,60 +315,29 @@ const handlerTop = async (conversation: ChatConversationVO) => {
await getChatConversationList() await getChatConversationList()
} }
// TODO @fan: ============ ============ // ============ ============
// ============
/** /** 角色仓库抽屉 */
* 角色仓库抽屉 const roleRepositoryOpen = ref<boolean>(false) //
*/
const handleRoleRepository = async () => { const handleRoleRepository = async () => {
drawer.value = !drawer.value roleRepositoryOpen.value = !roleRepositoryOpen.value
} }
// ============= /** 监听选中的对话 */
/**
* 清空对话
*/
const handleClearConversation = async () => {
// TODO @fan使 await message.confirm( 使 await
ElMessageBox.confirm('确认后对话会全部清空,置顶的对话除外。', '确认提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
await ChatConversationApi.deleteChatConversationMyByUnpinned()
ElMessage({
message: '操作成功!',
type: 'success'
})
//
activeConversationId.value = null
//
await getChatConversationList()
//
emits('onConversationClear')
})
.catch(() => {})
}
// ============ onMounted
const { activeId } = toRefs(props) const { activeId } = toRefs(props)
watch(activeId, async (newValue, oldValue) => { watch(activeId, async (newValue, oldValue) => {
//
activeConversationId.value = newValue as string activeConversationId.value = newValue as string
}) })
// public // public
defineExpose({ createConversation }) defineExpose({ createConversation })
/** 初始化 */
onMounted(async () => { onMounted(async () => {
// //
await getChatConversationList() await getChatConversationList()
// //
if (props.activeId != null) { if (props.activeId) {
activeConversationId.value = props.activeId activeConversationId.value = props.activeId
} else { } else {
// //

View File

@ -1,13 +1,20 @@
<template> <template>
<div class="category-list"> <div class="category-list">
<div class="category" v-for="(category) in categoryList" :key="category"> <div class="category" v-for="category in categoryList" :key="category">
<el-button plain round size="small" v-if="category !== active" @click="handleCategoryClick(category)">{{ category }}</el-button> <el-button
<el-button plain round size="small" v-else type="primary" @click="handleCategoryClick(category)">{{ category }}</el-button> plain
round
size="small"
:type="category === active ? 'primary' : ''"
@click="handleCategoryClick(category)"
>
{{ category }}
</el-button>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {PropType} from "vue"; import { PropType } from 'vue'
// //
defineProps({ defineProps({
@ -25,11 +32,10 @@ defineProps({
// //
const emits = defineEmits(['onCategoryClick']) const emits = defineEmits(['onCategoryClick'])
// /** 处理分类点击事件 */
const handleCategoryClick = async (category) => { const handleCategoryClick = async (category: string) => {
emits('onCategoryClick', category) emits('onCategoryClick', category)
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.category-list { .category-list {

View File

@ -1,22 +1,22 @@
<template> <template>
<div class="card-list" ref="tabsRef" @scroll="handleTabsScroll"> <div class="card-list" ref="tabsRef" @scroll="handleTabsScroll">
<div class="card-item" v-for="role in roleList" :key="role.id"> <div class="card-item" v-for="role in roleList" :key="role.id">
<el-card class="card" body-class="card-body"> <el-card class="card" body-class="card-body">
<!-- 更多 --> <!-- 更多操作 -->
<div class="more-container" v-if="showMore"> <div class="more-container" v-if="showMore">
<el-dropdown @command="handleMoreClick"> <el-dropdown @command="handleMoreClick">
<span class="el-dropdown-link"> <span class="el-dropdown-link">
<el-button type="text" > <el-button type="text">
<el-icon><More /></el-icon> <el-icon><More /></el-icon>
</el-button> </el-button>
</span> </span>
<!-- TODO @fan下面两个 icon可以使用类似 <Icon icon="ep:question-filled" /> 替代哈 --> <!-- TODO @fan下面两个 icon可以使用类似 <Icon icon="ep:question-filled" /> 替代哈 -->
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item :command="['edit', role]" > <el-dropdown-item :command="['edit', role]">
<el-icon><EditPen /></el-icon> <el-icon><EditPen /></el-icon>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item :command="['delete', role]" style="color: red;" > <el-dropdown-item :command="['delete', role]" style="color: red">
<el-icon><Delete /></el-icon> <el-icon><Delete /></el-icon>
<span>删除</span> <span>删除</span>
</el-dropdown-item> </el-dropdown-item>
@ -24,9 +24,9 @@
</template> </template>
</el-dropdown> </el-dropdown>
</div> </div>
<!-- 头像 --> <!-- 角色信息 -->
<div> <div>
<img class="avatar" :src="role.avatar"/> <img class="avatar" :src="role.avatar" />
</div> </div>
<div class="right-container"> <div class="right-container">
<div class="content-container"> <div class="content-container">
@ -43,9 +43,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ChatRoleVO} from '@/api/ai/model/chatRole' import { ChatRoleVO } from '@/api/ai/model/chatRole'
import {PropType, ref} from "vue"; import { PropType, ref } from 'vue'
import {Delete, EditPen, More} from "@element-plus/icons-vue"; import { Delete, EditPen, More } from '@element-plus/icons-vue'
const tabsRef = ref<any>() // tabs ref const tabsRef = ref<any>() // tabs ref
@ -65,10 +65,11 @@ const props = defineProps({
default: false default: false
} }
}) })
// //
const emits = defineEmits(['onDelete', 'onEdit', 'onUse', 'onPage']) const emits = defineEmits(['onDelete', 'onEdit', 'onUse', 'onPage'])
// more /** 操作:编辑、删除 */
const handleMoreClick = async (data) => { const handleMoreClick = async (data) => {
const type = data[0] const type = data[0]
const role = data[1] const role = data[1]
@ -79,28 +80,20 @@ const handleMoreClick = async (data) => {
} }
} }
// 使 /** 选中 */
const handleUseClick = (role) => { const handleUseClick = (role) => {
emits('onUse', role) emits('onUse', role)
} }
/** 滚动 */
const handleTabsScroll = async () => { const handleTabsScroll = async () => {
if (tabsRef.value) { if (tabsRef.value) {
const { scrollTop, scrollHeight, clientHeight } = tabsRef.value; const { scrollTop, scrollHeight, clientHeight } = tabsRef.value
console.log('scrollTop', scrollTop)
if (scrollTop + clientHeight >= scrollHeight - 20 && !props.loading) { if (scrollTop + clientHeight >= scrollHeight - 20 && !props.loading) {
console.log('分页')
// page.value++;
// fetchData(page.value);
await emits('onPage') await emits('onPage')
} }
} }
} }
onMounted(() => {
console.log('props', props.roleList)
})
</script> </script>
<style lang="scss"> <style lang="scss">
@ -114,11 +107,9 @@ onMounted(() => {
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
position: relative; position: relative;
} }
</style> </style>
<style scoped lang="scss"> <style scoped lang="scss">
// //
.card-list { .card-list {
display: flex; display: flex;
@ -180,9 +171,6 @@ onMounted(() => {
margin-top: 2px; margin-top: 2px;
} }
} }
} }
} }
</style> </style>

View File

@ -2,8 +2,8 @@
<template> <template>
<el-container class="role-container"> <el-container class="role-container">
<ChatRoleForm ref="formRef" @success="handlerAddRoleSuccess" /> <ChatRoleForm ref="formRef" @success="handlerAddRoleSuccess" />
<!-- header --> <!-- header -->
<Header title="角色仓库" style="position: relative" /> <RoleHeader title="角色仓库" class="relative" />
<!-- main --> <!-- main -->
<el-main class="role-main"> <el-main class="role-main">
<div class="search-container"> <div class="search-container">
@ -18,10 +18,10 @@
@change="getActiveTabsRole" @change="getActiveTabsRole"
/> />
<el-button <el-button
v-if="activeRole == 'my-role'" v-if="activeTab == 'my-role'"
type="primary" type="primary"
@click="handlerAddRole" @click="handlerAddRole"
style="margin-left: 20px" class="ml-20px"
> >
<!-- TODO @fan下面两个 icon可以使用类似 <Icon icon="ep:question-filled" /> 替代哈 --> <!-- TODO @fan下面两个 icon可以使用类似 <Icon icon="ep:question-filled" /> 替代哈 -->
<el-icon> <el-icon>
@ -31,7 +31,7 @@
</el-button> </el-button>
</div> </div>
<!-- tabs --> <!-- tabs -->
<el-tabs v-model="activeRole" class="tabs" @tab-click="handleTabsClick"> <el-tabs v-model="activeTab" class="tabs" @tab-click="handleTabsClick">
<el-tab-pane class="role-pane" label="我的角色" name="my-role"> <el-tab-pane class="role-pane" label="我的角色" name="my-role">
<RoleList <RoleList
:loading="loading" :loading="loading"
@ -41,7 +41,7 @@
@on-edit="handlerCardEdit" @on-edit="handlerCardEdit"
@on-use="handlerCardUse" @on-use="handlerCardUse"
@on-page="handlerCardPage('my')" @on-page="handlerCardPage('my')"
style="margin-top: 20px" class="mt-20px"
/> />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="公共角色" name="public-role"> <el-tab-pane label="公共角色" name="public-role">
@ -57,7 +57,7 @@
@on-edit="handlerCardEdit" @on-edit="handlerCardEdit"
@on-use="handlerCardUse" @on-use="handlerCardUse"
@on-page="handlerCardPage('public')" @on-page="handlerCardPage('public')"
style="margin-top: 20px" class="mt-20px"
loading loading
/> />
</el-tab-pane> </el-tab-pane>
@ -68,27 +68,30 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import Header from '../Header.vue' import RoleHeader from './RoleHeader.vue'
import RoleList from './RoleList.vue' import RoleList from './RoleList.vue'
import ChatRoleForm from '@/views/ai/model/chatRole/ChatRoleForm.vue' import ChatRoleForm from '@/views/ai/model/chatRole/ChatRoleForm.vue'
import RoleCategoryList from './RoleCategoryList.vue' import RoleCategoryList from './RoleCategoryList.vue'
import { ChatRoleApi, ChatRolePageReqVO, ChatRoleVO } from '@/api/ai/model/chatRole' import { ChatRoleApi, ChatRolePageReqVO, ChatRoleVO } from '@/api/ai/model/chatRole'
import { ChatConversationApi, ChatConversationVO } from '@/api/ai/chat/conversation' import { ChatConversationApi, ChatConversationVO } from '@/api/ai/chat/conversation'
import { TabsPaneContext } from 'element-plus'
import { Search, User } from '@element-plus/icons-vue' import { Search, User } from '@element-plus/icons-vue'
import { TabsPaneContext } from 'element-plus'
const router = useRouter() // const router = useRouter() //
// //
const loading = ref<boolean>(false) // const loading = ref<boolean>(false) //
const activeRole = ref<string>('my-role') // TODO @fan activeTab const activeTab = ref<string>('my-role') // Tab
const search = ref<string>('') // const search = ref<string>('') //
// TODO @fan myPagepubPage const queryParams = reactive({ const myRoleParams = reactive({
const myPageNo = ref<number>(1) // my pageNo: 1,
const myPageSize = ref<number>(50) // my pageSize: 50
})
const myRoleList = ref<ChatRoleVO[]>([]) // my const myRoleList = ref<ChatRoleVO[]>([]) // my
const publicPageNo = ref<number>(1) // public const publicRoleParams = reactive({
const publicPageSize = ref<number>(50) // public pageNo: 1,
pageSize: 50
})
const publicRoleList = ref<ChatRoleVO[]>([]) // public const publicRoleList = ref<ChatRoleVO[]>([]) // public
const activeCategory = ref<string>('全部') // const activeCategory = ref<string>('全部') //
const categoryList = ref<string[]>([]) // const categoryList = ref<string[]>([]) //
@ -96,7 +99,7 @@ const categoryList = ref<string[]>([]) // 角色分类类别
/** tabs 点击 */ /** tabs 点击 */
const handleTabsClick = async (tab: TabsPaneContext) => { const handleTabsClick = async (tab: TabsPaneContext) => {
// //
activeRole.value = tab.paneName + '' activeTab.value = tab.paneName + ''
// //
await getActiveTabsRole() await getActiveTabsRole()
} }
@ -104,12 +107,11 @@ const handleTabsClick = async (tab: TabsPaneContext) => {
/** 获取 my role 我的角色 */ /** 获取 my role 我的角色 */
const getMyRole = async (append?: boolean) => { const getMyRole = async (append?: boolean) => {
const params: ChatRolePageReqVO = { const params: ChatRolePageReqVO = {
pageNo: myPageNo.value, ...myRoleParams,
pageSize: myPageSize.value,
name: search.value, name: search.value,
publicStatus: false publicStatus: false
} }
const { total, list } = await ChatRoleApi.getMyPage(params) const { list } = await ChatRoleApi.getMyPage(params)
if (append) { if (append) {
myRoleList.value.push.apply(myRoleList.value, list) myRoleList.value.push.apply(myRoleList.value, list)
} else { } else {
@ -120,8 +122,7 @@ const getMyRole = async (append?: boolean) => {
/** 获取 public role 公共角色 */ /** 获取 public role 公共角色 */
const getPublicRole = async (append?: boolean) => { const getPublicRole = async (append?: boolean) => {
const params: ChatRolePageReqVO = { const params: ChatRolePageReqVO = {
pageNo: publicPageNo.value, ...publicRoleParams,
pageSize: publicPageSize.value,
category: activeCategory.value === '全部' ? '' : activeCategory.value, category: activeCategory.value === '全部' ? '' : activeCategory.value,
name: search.value, name: search.value,
publicStatus: true publicStatus: true
@ -136,20 +137,18 @@ const getPublicRole = async (append?: boolean) => {
/** 获取选中的 tabs 角色 */ /** 获取选中的 tabs 角色 */
const getActiveTabsRole = async () => { const getActiveTabsRole = async () => {
if (activeRole.value === 'my-role') { if (activeTab.value === 'my-role') {
myPageNo.value = 1 myRoleParams.pageNo = 1
await getMyRole() await getMyRole()
} else { } else {
publicPageNo.value = 1 publicRoleParams.pageNo = 1
await getPublicRole() await getPublicRole()
} }
} }
/** 获取角色分类列表 */ /** 获取角色分类列表 */
const getRoleCategoryList = async () => { const getRoleCategoryList = async () => {
const res = await ChatRoleApi.getCategoryList() categoryList.value = ['全部', ...(await ChatRoleApi.getCategoryList())]
const defaultRole = ['全部']
categoryList.value = [...defaultRole, ...res]
} }
/** 处理分类点击 */ /** 处理分类点击 */
@ -165,6 +164,10 @@ const formRef = ref()
const handlerAddRole = async () => { const handlerAddRole = async () => {
formRef.value.open('my-create', null, '添加角色') formRef.value.open('my-create', null, '添加角色')
} }
/** 编辑角色 */
const handlerCardEdit = async (role) => {
formRef.value.open('my-update', role.id, '编辑角色')
}
/** 添加角色成功 */ /** 添加角色成功 */
const handlerAddRoleSuccess = async (e) => { const handlerAddRoleSuccess = async (e) => {
@ -172,28 +175,22 @@ const handlerAddRoleSuccess = async (e) => {
await getActiveTabsRole() await getActiveTabsRole()
} }
// card /** 删除角色 */
const handlerCardDelete = async (role) => { const handlerCardDelete = async (role) => {
await ChatRoleApi.deleteMy(role.id) await ChatRoleApi.deleteMy(role.id)
// //
await getActiveTabsRole() await getActiveTabsRole()
} }
// card /** 角色分页:获取下一页 */
const handlerCardEdit = async (role) => {
formRef.value.open('my-update', role.id, '编辑角色')
}
/** card 分页:获取下一页 */
const handlerCardPage = async (type) => { const handlerCardPage = async (type) => {
console.log('handlerCardPage', type)
try { try {
loading.value = true loading.value = true
if (type === 'public') { if (type === 'public') {
publicPageNo.value++ publicRoleParams.pageNo++
await getPublicRole(true) await getPublicRole(true)
} else { } else {
myPageNo.value++ myRoleParams.pageNo++
await getMyRole(true) await getMyRole(true)
} }
} finally { } finally {
@ -208,10 +205,10 @@ const handlerCardUse = async (role) => {
roleId: role.id roleId: role.id
} as unknown as ChatConversationVO } as unknown as ChatConversationVO
const conversationId = await ChatConversationApi.createChatConversationMy(data) const conversationId = await ChatConversationApi.createChatConversationMy(data)
// 2. // 2.
// TODO @fan name~~~
await router.push({ await router.push({
path: `/ai/chat`, name: 'AiChat',
query: { query: {
conversationId: conversationId conversationId: conversationId
} }

View File

@ -19,11 +19,10 @@
<div class="btns" v-if="activeConversation"> <div class="btns" v-if="activeConversation">
<el-button type="primary" bg plain size="small" @click="openChatConversationUpdateForm"> <el-button type="primary" bg plain size="small" @click="openChatConversationUpdateForm">
<span v-html="activeConversation?.modelName"></span> <span v-html="activeConversation?.modelName"></span>
<Icon icon="ep:setting" style="margin-left: 10px" /> <Icon icon="ep:setting" class="ml-10px" />
</el-button> </el-button>
<el-button size="small" class="btn" @click="handlerMessageClear"> <el-button size="small" class="btn" @click="handlerMessageClear">
<!-- TODO @fanstyle 部分可以考虑用 unocss 替代 --> <img src="@/assets/ai/clear.svg" class="h-14px" />
<img src="@/assets/ai/clear.svg" style="height: 14px" />
</el-button> </el-button>
<!-- TODO @fan下面两个 icon可以使用类似 <Icon icon="ep:question-filled" /> 替代哈 --> <!-- TODO @fan下面两个 icon可以使用类似 <Icon icon="ep:question-filled" /> 替代哈 -->
<el-button size="small" :icon="Download" class="btn" /> <el-button size="small" :icon="Download" class="btn" />
@ -76,7 +75,7 @@
<div class="prompt-btns"> <div class="prompt-btns">
<div> <div>
<el-switch v-model="enableContext" /> <el-switch v-model="enableContext" />
<span style="font-size: 14px; color: #8f8f8f">上下文</span> <span class="ml-5px text-14px text-#8f8f8f">上下文</span>
</div> </div>
<el-button <el-button
type="primary" type="primary"
@ -119,6 +118,9 @@ import MessageLoading from './components/message/MessageLoading.vue'
import MessageNewConversation from './components/message/MessageNewConversation.vue' import MessageNewConversation from './components/message/MessageNewConversation.vue'
import { Download, Top } from '@element-plus/icons-vue' import { Download, Top } from '@element-plus/icons-vue'
/** AI 聊天对话 列表 */
defineOptions({ name: 'AiChat' })
const route = useRoute() // const route = useRoute() //
const message = useMessage() // const message = useMessage() //