dev #1
@ -29,6 +29,10 @@ export function fetchConversation(id: number, offset = 0) {
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteConversation(id: number) {
|
||||
return http.delete<ApiResponse<null>>(`/v1/conversations/${id}`);
|
||||
}
|
||||
|
||||
export function sendConversationMessage(
|
||||
id: number,
|
||||
content: string,
|
||||
|
||||
@ -95,6 +95,18 @@ async function openConversation(id: number) {
|
||||
}
|
||||
}
|
||||
|
||||
async function removeConversation(item: { id: number; title: string }) {
|
||||
if (!window.confirm(`确定删除会话“${item.title}”吗?删除后无法恢复。`)) return;
|
||||
try {
|
||||
await conversationStore.remove(item.id);
|
||||
if (conversationStore.current === null) {
|
||||
await router.push({ name: "assessment", query: { new: String(Date.now()) } });
|
||||
}
|
||||
} catch {
|
||||
// The store exposes the request error.
|
||||
}
|
||||
}
|
||||
|
||||
function searchConversations() {
|
||||
void conversationStore.loadList(search.value.trim() || undefined);
|
||||
}
|
||||
@ -131,14 +143,15 @@ function searchConversations() {
|
||||
<p v-else-if="!conversations.length" class="sidebar-state">
|
||||
暂无历史对话
|
||||
</p>
|
||||
<button
|
||||
<div
|
||||
v-for="item in conversations"
|
||||
:key="item.id"
|
||||
class="sidebar-item"
|
||||
:class="{
|
||||
'sidebar-item--active': conversationStore.current?.id === item.id,
|
||||
}"
|
||||
type="button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@click="openConversation(item.id)"
|
||||
>
|
||||
<span
|
||||
@ -148,7 +161,16 @@ function searchConversations() {
|
||||
></span>
|
||||
<span v-else class="risk-dot risk-dot--empty"></span>
|
||||
<span class="sidebar-item__label">{{ item.title }}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="sidebar-item__delete"
|
||||
title="删除会话"
|
||||
aria-label="删除会话"
|
||||
@click.stop="removeConversation(item)"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@ -264,6 +286,32 @@ section h2 {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sidebar-item__delete {
|
||||
display: none;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
flex: 0 0 22px;
|
||||
margin-left: auto;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: var(--color-text-faint);
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidebar-item:hover .sidebar-item__delete,
|
||||
.sidebar-item:focus-within .sidebar-item__delete {
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.sidebar-item__delete:hover {
|
||||
background: var(--color-danger-subtle);
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.risk-dot {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
|
||||
@ -3,6 +3,7 @@ import { computed, reactive, ref } from "vue";
|
||||
|
||||
import {
|
||||
createConversation,
|
||||
deleteConversation,
|
||||
fetchConversation,
|
||||
fetchConversations,
|
||||
withdrawConversationMessage,
|
||||
@ -132,6 +133,16 @@ export const useConversationStore = defineStore("conversation", () => {
|
||||
return current.value;
|
||||
}
|
||||
|
||||
async function remove(id: number) {
|
||||
const active = current.value?.id === id;
|
||||
await deleteConversation(id);
|
||||
streamStates.get(id)?.controller.abort();
|
||||
streamStates.delete(id);
|
||||
conversationCache.delete(id);
|
||||
items.value = items.value.filter((item) => item.id !== id);
|
||||
if (active) current.value = null;
|
||||
}
|
||||
|
||||
async function send(
|
||||
content: string,
|
||||
messageType: ConversationMessageType = "text",
|
||||
@ -428,6 +439,7 @@ export const useConversationStore = defineStore("conversation", () => {
|
||||
open,
|
||||
loadOlder,
|
||||
create,
|
||||
remove,
|
||||
send,
|
||||
streamSend,
|
||||
stopGeneration,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user