Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
f21991f4
authored
May 16, 2024
by
cherishsince
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【增加】AI 对话增加 GROUP 分组
parent
ad029830
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
102 additions
and
48 deletions
+102
-48
src/views/ai/chat/index.vue
+102
-48
No files found.
src/views/ai/chat/index.vue
View file @
f21991f4
...
...
@@ -5,7 +5,7 @@
<div>
<!-- 左顶部:新建对话 -->
<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>
<!-- 左顶部:搜索对话 -->
...
...
@@ -17,45 +17,50 @@
@
keyup=
"searchConversation"
>
<template
#
prefix
>
<Icon
icon=
"ep:search"
/>
<Icon
icon=
"ep:search"
/>
</
template
>
</el-input>
<!-- 左中间:对话列表 -->
<div
class=
"conversation-list"
>
<!-- TODO @fain:置顶、聊天记录、一星期钱、30天前,前端对数据重新做一下分组,或者后端接口改一下 -->
<div>
<el-text
class=
"mx-1"
size=
"small"
tag=
"b"
>
置顶
</el-text>
</div>
<el-row
v-for=
"conversation in conversationList"
:key=
"conversation.id"
@
click=
"handleConversationClick(conversation.id)"
>
<div
:class=
"conversation.id === conversationId ? 'conversation active' : 'conversation'"
@
click=
"changeConversation(conversation.id)"
>
<div
class=
"title-wrapper"
>
<img
class=
"avatar"
:src=
"conversation.roleAvatar"
/>
<span
class=
"title"
>
{{ conversation.title }}
</span>
</div>
<!-- TODO @fan:缺一个【置顶】按钮,效果改成 hover 上去展示 -->
<div
class=
"button-wrapper"
>
<el-icon
title=
"编辑"
@
click=
"updateConversationTitle(conversation)"
>
<Icon
icon=
"ep:edit"
/>
</el-icon>
<el-icon
title=
"删除会话"
@
click=
"deleteChatConversation(conversation)"
>
<Icon
icon=
"ep:delete"
/>
</el-icon>
</div>
<div
v-for=
"conversationKey in Object.keys(conversationMap)"
:key=
"conversationKey"
>
<div
v-if=
"conversationMap[conversationKey].length"
>
<el-text
class=
"mx-1"
size=
"small"
tag=
"b"
>
{{conversationKey}}
</el-text>
</div>
</el-row>
<el-row
v-for=
"conversation in conversationMap[conversationKey]"
:key=
"conversation.id"
@
click=
"handleConversationClick(conversation.id)"
>
<div
:class=
"conversation.id === conversationId ? 'conversation active' : 'conversation'"
@
click=
"changeConversation(conversation.id)"
>
<div
class=
"title-wrapper"
>
<img
class=
"avatar"
:src=
"conversation.roleAvatar"
/>
<span
class=
"title"
>
{{ conversation.title }}
</span>
</div>
<!-- TODO @fan:缺一个【置顶】按钮,效果改成 hover 上去展示 -->
<div
class=
"button-wrapper"
>
<el-icon
title=
"编辑"
@
click=
"updateConversationTitle(conversation)"
>
<Icon
icon=
"ep:edit"
/>
</el-icon>
<el-icon
title=
"删除会话"
@
click=
"deleteChatConversation(conversation)"
>
<Icon
icon=
"ep:delete"
/>
</el-icon>
</div>
</div>
</el-row>
</div>
</div>
</div>
<!-- 左底部:工具栏 -->
<div
class=
"tool-box"
>
<div
@
click=
"handleRoleRepository"
>
<Icon
icon=
"ep:user"
/>
<Icon
icon=
"ep:user"
/>
<el-text
size=
"small"
>
角色仓库
</el-text>
</div>
<div>
<Icon
icon=
"ep:delete"
/>
<Icon
icon=
"ep:delete"
/>
<el-text
size=
"small"
>
清空未置顶对话
</el-text>
</div>
</div>
...
...
@@ -71,16 +76,16 @@
<!-- TODO @fan:样式改下;这里我已经改成点击后,弹出了 -->
<el-button
type=
"primary"
@
click=
"openChatConversationUpdateForm"
>
<span
v-html=
"useConversation?.modelName"
></span>
<Icon
icon=
"ep:setting"
style=
"margin-left: 10px"
/>
<Icon
icon=
"ep:setting"
style=
"margin-left: 10px"
/>
</el-button>
<el-button>
<Icon
icon=
"ep:user"
/>
<Icon
icon=
"ep:user"
/>
</el-button>
<el-button>
<Icon
icon=
"ep:download"
/>
<Icon
icon=
"ep:download"
/>
</el-button>
<el-button>
<Icon
icon=
"ep:arrow-up"
/>
<Icon
icon=
"ep:arrow-up"
/>
</el-button>
</div>
</el-header>
...
...
@@ -107,11 +112,11 @@
</div>
<div
class=
"left-btns"
>
<div
class=
"btn-cus"
@
click=
"noCopy(item.content)"
>
<img
class=
"btn-image"
src=
"../../../assets/ai/copy.svg"
/>
<img
class=
"btn-image"
src=
"../../../assets/ai/copy.svg"
/>
<el-text
class=
"btn-cus-text"
>
复制
</el-text>
</div>
<div
class=
"btn-cus"
style=
"margin-left: 20px"
@
click=
"onDelete(item.id)"
>
<img
class=
"btn-image"
src=
"@/assets/ai/delete.svg"
style=
"height: 17px"
/>
<img
class=
"btn-image"
src=
"@/assets/ai/delete.svg"
style=
"height: 17px"
/>
<el-text
class=
"btn-cus-text"
>
删除
</el-text>
</div>
</div>
...
...
@@ -133,11 +138,11 @@
</div>
<div
class=
"right-btns"
>
<div
class=
"btn-cus"
@
click=
"noCopy(item.content)"
>
<img
class=
"btn-image"
src=
"@/assets/ai/copy.svg"
/>
<img
class=
"btn-image"
src=
"@/assets/ai/copy.svg"
/>
<el-text
class=
"btn-cus-text"
>
复制
</el-text>
</div>
<div
class=
"btn-cus"
style=
"margin-left: 20px"
@
click=
"onDelete(item.id)"
>
<img
class=
"btn-image"
src=
"@/assets/ai/delete.svg"
style=
"height: 17px"
/>
<img
class=
"btn-image"
src=
"@/assets/ai/delete.svg"
style=
"height: 17px"
/>
<el-text
class=
"btn-cus-text"
>
删除
</el-text>
</div>
</div>
...
...
@@ -145,10 +150,10 @@
</div>
</div>
</div>
<!-- 角色仓库抽屉 -->
<el-drawer
v-model=
"drawer"
title=
"角色仓库"
size=
"50%"
>
<Role
/>
</el-drawer>
<!-- 角色仓库抽屉 -->
<el-drawer
v-model=
"drawer"
title=
"角色仓库"
size=
"50%"
>
<Role
/>
</el-drawer>
</el-main>
<el-footer
class=
"footer-container"
>
<form
@
submit
.
prevent=
"onSend"
class=
"prompt-from"
>
...
...
@@ -162,7 +167,7 @@
placeholder=
"问我任何问题...(Shift+Enter 换行,按下 Enter 发送)"
></textarea>
<div
class=
"prompt-btns"
>
<el-switch
/>
<el-switch/>
<el-button
type=
"primary"
size=
"default"
...
...
@@ -193,24 +198,25 @@
</template>
<
script
setup
lang=
"ts"
>
import
{
ChatMessageApi
,
ChatMessageSendVO
,
ChatMessageVO
}
from
'@/api/ai/chat/message'
import
{
ChatConversationApi
,
ChatConversationVO
}
from
'@/api/ai/chat/conversation'
import
{
ChatMessageApi
,
ChatMessageVO
}
from
'@/api/ai/chat/message'
import
{
ChatConversationApi
,
ChatConversationVO
}
from
'@/api/ai/chat/conversation'
import
ChatConversationUpdateForm
from
'./components/ChatConversationUpdateForm.vue'
import
Role
from
'@/views/ai/chat/role/index.vue'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
useClipboard
}
from
'@vueuse/core'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
useClipboard
}
from
'@vueuse/core'
// 转换 markdown
import
{
marked
}
from
'marked'
import
{
marked
}
from
'marked'
// 代码高亮 https://highlightjs.org/
import
'highlight.js/styles/vs2015.min.css'
import
hljs
from
'highlight.js'
const
route
=
useRoute
()
// 路由
const
message
=
useMessage
()
// 消息弹窗
// 自定义渲染器
const
renderer
=
{
code
(
code
,
language
,
c
)
{
const
highlightHtml
=
hljs
.
highlight
(
code
,
{
language
:
language
,
ignoreIllegals
:
true
}).
value
const
highlightHtml
=
hljs
.
highlight
(
code
,
{
language
:
language
,
ignoreIllegals
:
true
}).
value
const
copyHtml
=
`<div id="copy" data-copy='
${
code
}
' style="position: absolute; right: 10px; top: 5px; color: #fff;cursor: pointer;">复制</div>`
return
`<pre>
${
copyHtml
}
<code class="hljs">
${
highlightHtml
}
</code></pre>`
}
...
...
@@ -220,8 +226,9 @@ marked.use({
})
const
conversationList
=
ref
([]
as
ChatConversationVO
[])
const
conversationMap
=
ref
<
any
>
({})
// 初始化 copy 到粘贴板
const
{
copy
}
=
useClipboard
()
const
{
copy
}
=
useClipboard
()
const
drawer
=
ref
<
boolean
>
(
false
)
// 角色仓库抽屉
const
searchName
=
ref
(
''
)
// 查询的内容
...
...
@@ -261,7 +268,7 @@ const changeConversation = (id: number) => {
/** 更新聊天会话的标题 */
const
updateConversationTitle
=
async
(
conversation
:
ChatConversationVO
)
=>
{
// 二次确认
const
{
value
}
=
await
ElMessageBox
.
prompt
(
'修改标题'
,
{
const
{
value
}
=
await
ElMessageBox
.
prompt
(
'修改标题'
,
{
inputPattern
:
/^
[\s\S]
*.*
\S[\s\S]
*$/
,
// 判断非空,且非空格
inputErrorMessage
:
'标题不能为空'
,
inputValue
:
conversation
.
title
...
...
@@ -286,7 +293,8 @@ const deleteChatConversation = async (conversation: ChatConversationVO) => {
message
.
success
(
'会话已删除'
)
// 刷新列表
await
getChatConversationList
()
}
catch
{}
}
catch
{
}
}
const
searchConversation
=
()
=>
{
...
...
@@ -532,8 +540,54 @@ const getChatConversationList = async () => {
changeConversation
(
conversationList
.
value
[
0
].
id
)
}
}
// map
const
groupRes
=
await
conversationTimeGroup
(
conversationList
.
value
)
conversationMap
.
value
=
groupRes
}
const
conversationTimeGroup
=
async
(
list
:
ChatConversationVO
[])
=>
{
// 排序、指定、时间分组(今天、一天前、三天前、七天前、30天前)
const
groupMap
=
{
'置顶'
:
[],
'今天'
:
[],
'一天前'
:
[],
'三天前'
:
[],
'七天前'
:
[],
'三十天前'
:
[]
}
// 当前时间的时间戳
const
now
=
Date
.
now
();
// 定义时间间隔常量(单位:毫秒)
const
oneDay
=
24
*
60
*
60
*
1000
;
const
threeDays
=
3
*
oneDay
;
const
sevenDays
=
7
*
oneDay
;
const
thirtyDays
=
30
*
oneDay
;
console
.
log
(
'listlistlist'
,
list
)
for
(
const
conversation
:
ChatConversationVO
of
list
)
{
// 置顶
if
(
conversation
.
pinned
)
{
groupMap
[
'置顶'
].
push
(
conversation
)
continue
}
// 计算时间差(单位:毫秒)
const
diff
=
now
-
conversation
.
updateTime
;
// 根据时间间隔判断
if
(
diff
<
oneDay
)
{
groupMap
[
'今天'
].
push
(
conversation
)
}
else
if
(
diff
<
threeDays
)
{
groupMap
[
'一天前'
].
push
(
conversation
)
}
else
if
(
diff
<
sevenDays
)
{
groupMap
[
'三天前'
].
push
(
conversation
)
}
else
if
(
diff
<
thirtyDays
)
{
groupMap
[
'七天前'
].
push
(
conversation
)
}
else
{
groupMap
[
'三十天前'
].
push
(
conversation
)
}
}
return
groupMap
}
// 对话点击
const
handleConversationClick
=
async
(
id
:
number
)
=>
{
// 切换对话
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment