|
@@ -33,57 +33,7 @@ for (let i = 0; i < 100; i++) {
|
|
|
}
|
|
|
|
|
|
// 消息列表
|
|
|
-const messages = ref<Message[]>([
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- type: 'user',
|
|
|
- content: '请帮我分析这个数据',
|
|
|
- timestamp: new Date()
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- type: 'ai',
|
|
|
- content: `好的,我来为您查询相关的人员信息。首先请让我从数据库中获取所有相关百科:
|
|
|
-
|
|
|
-## Tool Calls 📊
|
|
|
-
|
|
|
-\`\`\`json
|
|
|
-{
|
|
|
- "id": "XXX",
|
|
|
- "params": "yyy",
|
|
|
- "returns": "zzz"
|
|
|
-}
|
|
|
-\`\`\`
|
|
|
-
|
|
|
-...ListItem
|
|
|
-
|
|
|
-根据我查询到的信息,我找到您想要的相关人员信息:
|
|
|
-
|
|
|
-1. xxxxx
|
|
|
-2. yyyyy
|
|
|
-3. zzzzz
|
|
|
-
|
|
|
-\`\`\`echarts
|
|
|
-{
|
|
|
- "title": {
|
|
|
- "text": "charts 1"
|
|
|
- },
|
|
|
- "xAxis": {
|
|
|
- "type": "category",
|
|
|
- "data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
|
|
- },
|
|
|
- "yAxis": {
|
|
|
- "type": "value"
|
|
|
- },
|
|
|
- "series": [{
|
|
|
- "data": [120, 200, 150, 80, 70, 110, 130],
|
|
|
- "type": "bar"
|
|
|
- }]
|
|
|
-}
|
|
|
-\`\`\``,
|
|
|
- timestamp: new Date()
|
|
|
- }
|
|
|
-])
|
|
|
+const messages = ref<Message[]>([])
|
|
|
|
|
|
// 输入框内容
|
|
|
const inputMessage = ref('')
|
|
@@ -280,33 +230,100 @@ onMounted(() => {
|
|
|
<el-main class="chat-main">
|
|
|
<!-- 消息展示区域 -->
|
|
|
<div class="messages-container" ref="messagesContainer">
|
|
|
- <div
|
|
|
- v-for="message in messages"
|
|
|
- :key="message.id"
|
|
|
- :class="['message-wrapper', message.type]"
|
|
|
- >
|
|
|
- <!-- AI消息 -->
|
|
|
- <div v-if="message.type === 'ai'" class="ai-message-container">
|
|
|
- <el-avatar class="message-avatar" :icon="ChatDotRound" />
|
|
|
- <div class="message-bubble ai-bubble">
|
|
|
- <Markdown
|
|
|
- :content="message.content"
|
|
|
- :plugins="plugins"
|
|
|
- class="markdown-content"
|
|
|
+ <div v-if="messages.length !== 0">
|
|
|
+ <div
|
|
|
+ v-for="message in messages"
|
|
|
+ :key="message.id"
|
|
|
+ :class="['message-wrapper', message.type]"
|
|
|
+ >
|
|
|
+ <!-- AI消息 -->
|
|
|
+ <div v-if="message.type === 'ai'" class="ai-message-container">
|
|
|
+ <el-avatar class="message-avatar" :icon="ChatDotRound" />
|
|
|
+ <div class="message-bubble ai-bubble">
|
|
|
+ <Markdown
|
|
|
+ :content="message.content"
|
|
|
+ :plugins="plugins"
|
|
|
+ class="markdown-content"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 用户消息 -->
|
|
|
+ <div v-else class="user-message-container">
|
|
|
+ <div class="message-bubble user-bubble">
|
|
|
+ {{ message.content }}
|
|
|
+ </div>
|
|
|
+ <el-avatar
|
|
|
+ class="message-avatar"
|
|
|
+ :src="getUserInfos.avatar"
|
|
|
+ :icon="User"
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 空状态页面 -->
|
|
|
+
|
|
|
+ <div class="empty-content">
|
|
|
+ <!-- 主图标 -->
|
|
|
+ <div class="empty-icon">
|
|
|
+ <el-icon :size="80" color="#d1d5db">
|
|
|
+ <ChatDotRound />
|
|
|
+ </el-icon>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 标题和描述 -->
|
|
|
+ <div class="empty-text">
|
|
|
+ <h2 class="empty-title">开始新的对话</h2>
|
|
|
+ <p class="empty-description">
|
|
|
+ 选择工具和模型,然后在下方输入您的问题开始对话
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ <!-- 快速开始提示 -->
|
|
|
+ <div class="quick-start">
|
|
|
+ <div class="quick-start-item">
|
|
|
+ <span class="step-number">1</span>
|
|
|
+ <span class="step-text">选择需要的工具</span>
|
|
|
+ </div>
|
|
|
+ <div class="quick-start-item">
|
|
|
+ <span class="step-number">2</span>
|
|
|
+ <span class="step-text">选择AI模型</span>
|
|
|
+ </div>
|
|
|
+ <div class="quick-start-item">
|
|
|
+ <span class="step-number">3</span>
|
|
|
+ <span class="step-text">输入问题并发送</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
- <!-- 用户消息 -->
|
|
|
- <div v-else class="user-message-container">
|
|
|
- <div class="message-bubble user-bubble">
|
|
|
- {{ message.content }}
|
|
|
+ <!-- 示例问题 -->
|
|
|
+ <div class="example-questions">
|
|
|
+ <h4>试试这些问题:</h4>
|
|
|
+ <div class="question-tags">
|
|
|
+ <el-tag
|
|
|
+ class="question-tag"
|
|
|
+ @click="inputMessage = '帮我查看设备运行状态和告警信息'"
|
|
|
+ type="info"
|
|
|
+ >
|
|
|
+ 帮我查看设备运行状态和告警信息
|
|
|
+ </el-tag>
|
|
|
+ <el-tag
|
|
|
+ class="question-tag"
|
|
|
+ @click="inputMessage = '分析用户权限配置和角色分配情况'"
|
|
|
+ type="success"
|
|
|
+ >
|
|
|
+ 分析用户权限配置和角色分配情况
|
|
|
+ </el-tag>
|
|
|
+ <el-tag
|
|
|
+ class="question-tag"
|
|
|
+ @click="inputMessage = '检查系统性能和在线用户统计'"
|
|
|
+ type="warning"
|
|
|
+ >
|
|
|
+ 检查系统性能和在线用户统计
|
|
|
+ </el-tag>
|
|
|
</div>
|
|
|
- <el-avatar
|
|
|
- class="message-avatar"
|
|
|
- :src="getUserInfos.avatar"
|
|
|
- :icon="User"
|
|
|
- />
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
@@ -711,26 +728,105 @@ onMounted(() => {
|
|
|
}
|
|
|
|
|
|
/* 响应式调整 */
|
|
|
-@media (max-width: 768px) {
|
|
|
- .input-container {
|
|
|
- width: 95%;
|
|
|
- padding: 12px;
|
|
|
- }
|
|
|
+/* 空状态页面样式 */
|
|
|
+.empty-content {
|
|
|
+ text-align: center;
|
|
|
+ max-width: 600px;
|
|
|
+ width: 100%;
|
|
|
|
|
|
- .selection-row {
|
|
|
- flex-direction: column;
|
|
|
- align-items: stretch;
|
|
|
- gap: 8px;
|
|
|
- }
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ top: 50%;
|
|
|
+ transform: translate(-50%,-50%);
|
|
|
+}
|
|
|
+
|
|
|
+.empty-icon {
|
|
|
+ margin-bottom: 24px;
|
|
|
+ opacity: 0.6;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-text {
|
|
|
+ margin-bottom: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-title {
|
|
|
+ font-size: 28px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
+ margin: 0 0 12px 0;
|
|
|
+}
|
|
|
|
|
|
- .tool-selector,
|
|
|
- .model-selector {
|
|
|
- width: 100%;
|
|
|
+.empty-description {
|
|
|
+ font-size: 16px;
|
|
|
+ color: var(--el-text-color-regular);
|
|
|
+ margin: 0;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+.quick-start {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 40px;
|
|
|
+ margin-bottom: 40px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+}
|
|
|
+
|
|
|
+.quick-start-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ color: var(--el-text-color-regular);
|
|
|
+}
|
|
|
+
|
|
|
+.step-number {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ background: var(--el-color-primary);
|
|
|
+ color: white;
|
|
|
+ border-radius: 50%;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 600;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.step-text {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.example-questions {
|
|
|
+ h4 {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: var(--el-text-color-primary);
|
|
|
+ margin: 0 0 16px 0;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- .tool-selector :deep(.el-cascader),
|
|
|
- .model-selector :deep(.el-select) {
|
|
|
- width: 100% !important;
|
|
|
+.question-tags {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 12px;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.question-tag {
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.2s ease;
|
|
|
+ font-size: 13px;
|
|
|
+ padding: 8px 16px;
|
|
|
+ border-radius: 20px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ transform: translateY(-1px);
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
</style>
|