Files
Ars-Font/src/components/NewChatButton.vue

166 lines
3.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import axios from 'axios'
import { ElMessage } from 'element-plus'
const props = defineProps({
inline: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['created'])
const router = useRouter()
const apiBase = import.meta.env.VITE_API_BASE || 'http://localhost:8000/api'
const creating = ref(false)
const sessionName = ref('')
const lastSessionId = ref(localStorage.getItem('ars-last-session') || '')
const popoverVisible = ref(false)
const togglePopover = () => {
popoverVisible.value = !popoverVisible.value
}
const createSession = async () => {
const token = localStorage.getItem('ars-token') || ''
if (!token) {
router.replace({ name: 'login' })
return
}
creating.value = true
const payload = {
session_name: sessionName.value.trim() || '新会话',
}
try {
const { data } = await axios.post(`${apiBase}/sessions`, payload, {
headers: { Authorization: `Bearer ${token}` },
})
lastSessionId.value = data.session_id
localStorage.setItem('ars-last-session', data.session_id)
ElMessage.success('新会话已创建')
sessionName.value = ''
popoverVisible.value = false
emit('created', data)
} catch (err) {
const message = err.response?.data?.message || '创建会话失败'
ElMessage.error(message)
if (err.response?.status === 401) {
router.replace({ name: 'login' })
}
} finally {
creating.value = false
}
}
</script>
<template>
<el-popover
v-model:visible="popoverVisible"
trigger="manual"
placement="bottom-start"
popper-class="mini-popper"
width="260"
:teleported="false"
>
<template #reference>
<button
class="new-chat-btn"
:class="{ inline: props.inline }"
aria-label="新建会话"
data-testid="new-chat-trigger"
@click.stop="togglePopover"
>
<span class="plus"></span>
<span class="label">新建聊天</span>
</button>
</template>
<div class="new-chat-card">
<p class="title">新建 Chat Session</p>
<el-input
v-model="sessionName"
size="large"
placeholder="可选:会话名称"
data-testid="session-name"
/>
<el-button
type="primary"
class="create-btn"
color="#1d4ed8"
:loading="creating"
data-testid="create-session"
@click="createSession"
>
创建
</el-button>
<p v-if="lastSessionId" class="last">
最近会话<code>{{ lastSessionId }}</code>
</p>
</div>
</el-popover>
</template>
<style scoped>
.new-chat-btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-radius: 12px;
border: 1px solid rgba(0, 0, 0, 0.08);
background: rgba(255, 255, 255, 0.88);
box-shadow: 0 8px 20px rgba(17, 24, 39, 0.12);
cursor: pointer;
transition: transform 0.18s ease, box-shadow 0.18s ease;
color: #111827;
}
.new-chat-btn.inline {
width: 100%;
justify-content: center;
box-shadow: none;
border: 1px solid rgba(0, 0, 0, 0.04);
}
.new-chat-btn:hover {
transform: translateY(-2px);
box-shadow: 0 12px 28px rgba(17, 24, 39, 0.15);
}
.plus {
font-size: 18px;
font-weight: 700;
}
.label {
font-weight: 700;
letter-spacing: 0.02em;
}
.new-chat-card {
display: flex;
flex-direction: column;
gap: 10px;
}
.title {
margin: 0;
font-weight: 700;
color: #0f172a;
}
.create-btn {
width: 100%;
font-weight: 700;
}
.last {
margin: 0;
font-size: 12px;
color: #4b5563;
word-break: break-all;
}
</style>