Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
A
ai-chat-ui
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
chenghong_tao
ai-chat-ui
Commits
2b895f7e
Commit
2b895f7e
authored
Apr 28, 2025
by
chenghong_tao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix loading
parent
c6b82368
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
36 additions
and
66 deletions
+36
-66
Chat.vue
src/components/Chat.vue
+7
-25
HistoryList.vue
src/components/HistoryList.vue
+4
-2
Layout.vue
src/components/Layout.vue
+12
-2
aiBubble.vue
src/components/chatSubassembly/aiBubble.vue
+8
-10
inputMessage.vue
src/components/chatSubassembly/inputMessage.vue
+5
-27
No files found.
src/components/Chat.vue
View file @
2b895f7e
...
...
@@ -14,8 +14,6 @@
:historyMsgId=
"item?.id"
:messageType=
"item.type"
:content=
"item.content"
@
messageFinished=
"messageFinished"
@
workflow-is-error=
"workflowIsError"
/>
<userBubble
v-else
:content=
"item.content"
/>
</div>
...
...
@@ -23,7 +21,7 @@
</div>
</el-scrollbar>
<div
class=
"input-box"
>
<InputMessage
ref=
"inputMessageRef"
@
userQuery=
"userQuery"
@
getInputHeight=
"getInputHeight"
:loadingFinished=
"loadingFinished"
:workflowError=
"workflowError"
/>
<InputMessage
ref=
"inputMessageRef"
@
userQuery=
"userQuery"
@
getInputHeight=
"getInputHeight"
/>
</div>
</template>
<
script
setup
>
...
...
@@ -89,32 +87,10 @@ const getInputHeight = (height) => {
defaultHeight
.
value
=
height
+
marginTop
}
const
loadingFinished
=
ref
(
false
)
const
messageFinished
=
(
status
)
=>
{
loadingFinished
.
value
=
status
if
(
!
status
)
{
loadingFinished
.
value
=
true
nextTick
(()
=>
{
loadingFinished
.
value
=
status
})
}
if
(
status
)
{
nextTick
(()
=>
{
scrollToBottom
()
})
clearInterval
(
scrollTimer
.
value
);
}
}
const
hasWelcomeMessage
=
computed
(()
=>
{
return
appStore
.
appParams
.
opening_statement
!=
''
;
});
const
workflowError
=
ref
(
false
)
const
workflowIsError
=
(
isError
)
=>
{
workflowError
.
value
=
isError
}
// 滚动到底部
const
scrollToBottom
=
async
()
=>
{
if
(
scrollbarRef
.
value
)
{
...
...
@@ -148,6 +124,12 @@ watch(() => props.historyMsgList, (newValue) => {
},
{
immediate
:
true
})
})
watch
(()
=>
taskStore
.
isLoading
,
(
newValue
)
=>
{
if
(
!
newValue
)
{
clearInterval
(
scrollTimer
.
value
)
}
})
defineExpose
({
resetChat
})
...
...
src/components/HistoryList.vue
View file @
2b895f7e
...
...
@@ -72,6 +72,7 @@ const keyword = ref("");
const
filteredList
=
ref
([]);
const
currentClickItemId
=
ref
(
null
);
const
emits
=
defineEmits
([
"getHistoryMsg"
,
"refreshConversation"
]);
const
getHistoryList
=
async
()
=>
{
const
historyResult
=
await
difyApi
.
getChatList
({
limit
:
100
});
list
.
value
=
historyResult
.
data
;
...
...
@@ -96,6 +97,9 @@ const openDeleteConfirm = (id) => {
const
deleteChat
=
async
(
id
)
=>
{
await
difyApi
.
deleteChat
(
id
);
getHistoryList
();
if
(
taskStore
.
conversation_id
)
{
emits
(
"refreshConversation"
);
}
};
// 防抖函数
...
...
@@ -121,8 +125,6 @@ const debouncedFilterList = debounce(filterList, 300); // 300 毫秒的防抖时
watch
(
keyword
,
debouncedFilterList
);
const
emits
=
defineEmits
([
"getHistoryMsg"
]);
const
getConversationMsg
=
async
(
id
)
=>
{
currentClickItemId
.
value
=
id
;
const
result
=
await
difyApi
.
getChatHistory
({
...
...
src/components/Layout.vue
View file @
2b895f7e
...
...
@@ -3,7 +3,12 @@
<el-container>
<transition
name=
"slide"
>
<el-aside
width=
"280px"
v-show=
"sideBarHidden"
>
<HistoryList
@
getHistoryMsg=
"getHistoryMsg"
:isRefreshHistoryList=
"isRefreshHistoryList"
:isResetHistoryItem=
"isResetHistoryItem"
/>
<HistoryList
@
getHistoryMsg=
"getHistoryMsg"
:isRefreshHistoryList=
"isRefreshHistoryList"
:isResetHistoryItem=
"isResetHistoryItem"
@
refreshConversation=
"refreshConversation"
/>
</el-aside>
</transition>
<el-container
id=
"main-container"
>
...
...
@@ -11,7 +16,12 @@
<Header
@
getSideBarStatus=
"getSideBarStatus"
@
refreshConversation=
"refreshConversation"
/>
</el-header>
<el-main>
<Chat
ref=
"chatRef"
v-if=
"!refreshChat"
:historyMsgList=
"historyMsgList"
@
updateHistory=
"refreshHistoryList"
/>
<Chat
ref=
"chatRef"
v-if=
"!refreshChat"
:historyMsgList=
"historyMsgList"
@
updateHistory=
"refreshHistoryList"
/>
</el-main>
</el-container>
</el-container>
...
...
src/components/chatSubassembly/aiBubble.vue
View file @
2b895f7e
...
...
@@ -84,6 +84,9 @@ const avatarAi = "./avatarAI.svg";
const
clickLike
=
ref
(
false
)
const
clickDisLike
=
ref
(
false
)
const
isReStartWorkflow
=
ref
(
false
)
const
workflowStatus
=
ref
(
null
)
const
props
=
defineProps
({
query
:
{
type
:
Array
,
...
...
@@ -103,8 +106,6 @@ const props = defineProps({
},
});
const
emits
=
defineEmits
([
"messageFinished"
,
"workflow-is-error"
]);
watch
(
()
=>
props
.
query
,
(
newValue
)
=>
{
...
...
@@ -120,11 +121,11 @@ watch(() => isLoading.value, (newValue) => {
taskStore
.
setIsLoading
(
newValue
)
})
const
isReStartWorkflow
=
ref
(
false
)
const
workflowStatus
=
ref
(
null
)
// 默认支持 SSE 协议
async
function
startSSE
(
query
)
{
try
{
taskStore
.
setIsLoading
(
true
)
workflowStatus
.
value
=
'loading'
;
const
chatMessageOptions
=
difyApi
.
chatMessage
()
const
response
=
await
fetch
(
chatMessageOptions
.
url
,
{
headers
:
chatMessageOptions
.
headers
,
...
...
@@ -142,6 +143,7 @@ async function startSSE(query) {
await
startStream
({
readableStream
});
}
catch
(
err
)
{
console
.
error
(
"Fetch error:"
,
err
);
taskStore
.
setIsLoading
(
false
)
}
}
...
...
@@ -160,9 +162,6 @@ const workflowContent = computed(() => {
const
parsedChunk
=
JSON
.
parse
(
chunk
);
workflowList
.
push
(
parsedChunk
);
if
(
parsedChunk
.
event
===
"workflow_started"
)
{
workflowStatus
.
value
=
'loading'
;
console
.
log
(
"workflow_started"
,
parsedChunk
);
taskStore
.
setTaskId
(
parsedChunk
.
task_id
);
taskStore
.
setConversationId
(
parsedChunk
.
conversation_id
);
taskStore
.
setMessageId
(
parsedChunk
.
message_id
);
...
...
@@ -171,12 +170,12 @@ const workflowContent = computed(() => {
if
(
parsedChunk
.
event
===
"error"
)
{
ElMessage
.
error
(
parsedChunk
.
message
)
workflowStatus
.
value
=
'error'
;
emit
(
'workflow-is-error'
,
tru
e
)
taskStore
.
setIsLoading
(
fals
e
)
break
;
}
if
(
parsedChunk
.
event
===
"message_end"
)
{
workflowStatus
.
value
=
'success'
;
emits
(
"messageFinished"
,
true
);
taskStore
.
setIsLoading
(
false
)
}
}
catch
(
error
)
{
// 实际项目中,以项目需要为准
...
...
@@ -199,7 +198,6 @@ const reStartSSE = () => {
// if(workflowItemRef.value) {
// workflowItemRef.value.clearWorkflow();
// }
emits
(
"messageFinished"
,
false
);
startSSE
(
props
.
query
);
console
.
log
(
'reStartSSE'
,
props
.
query
,
props
.
messageType
,
props
.
content
)
};
...
...
src/components/chatSubassembly/inputMessage.vue
View file @
2b895f7e
...
...
@@ -57,33 +57,6 @@ import { Close, Promotion, Loading } from "@element-plus/icons-vue";
import
difyApi
from
"../../apis/difyApi"
;
import
{
useTaskStore
}
from
"../../store/task"
;
const
props
=
defineProps
({
loadingFinished
:
{
type
:
Boolean
,
default
:
false
,
},
workflowError
:
{
type
:
Boolean
,
default
:
false
,
},
});
watch
(
()
=>
props
.
loadingFinished
,
(
newValue
)
=>
{
senderLoading
.
value
=
!
newValue
;
}
);
watch
(
()
=>
props
.
workflowError
,
(
newValue
)
=>
{
if
(
newValue
)
{
senderLoading
.
value
=
false
;
}
}
);
const
taskStore
=
useTaskStore
();
const
senderRef
=
ref
();
const
senderValue
=
ref
(
""
);
...
...
@@ -95,6 +68,10 @@ watch(() => deepThink.value, (newValue) => {
taskStore
.
setDeepThink
(
newValue
)
})
watch
(()
=>
taskStore
.
isLoading
,
(
newValue
)
=>
{
senderLoading
.
value
=
newValue
;
})
const
emit
=
defineEmits
([
"userQuery"
,
"getInputHeight"
]);
function
handleSubmit
()
{
senderLoading
.
value
=
true
;
...
...
@@ -116,6 +93,7 @@ const handleCancel = async () => {
await
difyApi
.
stop
(
taskStore
.
taskId
);
}
senderLoading
.
value
=
false
;
taskStore
.
setIsLoading
(
false
);
};
const
changeLoading
=
(
loading
)
=>
{
...
...
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