|
@@ -5,6 +5,32 @@
|
|
|
v-model:visible="showPasswordDialog"
|
|
|
/>
|
|
|
|
|
|
+ <!-- 进度条弹窗组件 -->
|
|
|
+ <div v-if="showProgressModal" class="progress-modal-overlay">
|
|
|
+ <div class="progress-modal">
|
|
|
+ <div class="progress-modal-header">
|
|
|
+ <h3>处理进度</h3>
|
|
|
+ <button class="close-btn" @click="closeProgressModal">×</button>
|
|
|
+ </div>
|
|
|
+ <div class="progress-list">
|
|
|
+ <div
|
|
|
+ v-for="(progress, index) in progressList"
|
|
|
+ :key="index"
|
|
|
+ class="progress-item"
|
|
|
+ >
|
|
|
+ <div class="progress-info">
|
|
|
+ <span class="progress-title">{{ progress.title }}</span>
|
|
|
+ <span class="progress-percentage">{{ progress.value }}%</span>
|
|
|
+ </div>
|
|
|
+ <div class="progress-bar-container">
|
|
|
+ <div class="progress-bar" :style="{ width: progress.value + '%' }"></div>
|
|
|
+ </div>
|
|
|
+ <div class="progress-status">{{ progress.status }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div class="header">
|
|
|
<div class="user-profile-bar">
|
|
|
<div class="logo">
|
|
@@ -260,11 +286,18 @@
|
|
|
<div class="message-content">
|
|
|
<!-- 添加thinking steps显示 -->
|
|
|
<div v-if="message.thinkingSteps && message.thinkingSteps.length > 0" class="thinking-steps">
|
|
|
+ <!-- <div class="thinking-steps-header">
|
|
|
+ <span class="thinking-title">🤔 思考过程</span>
|
|
|
+ </div> :class="step.type"-->
|
|
|
<div v-for="(step, index) in message.thinkingSteps"
|
|
|
:key="index"
|
|
|
class="thinking-step"
|
|
|
- :class="step.type">
|
|
|
- {{ step.content }}
|
|
|
+ >
|
|
|
+ <div class="step-content">{{ step.content }}</div>
|
|
|
+ <!-- <div class="step-meta">
|
|
|
+ <span class="step-type">{{ getStepTypeName(step.type) }}</span>
|
|
|
+ <span class="step-confidence">置信度: {{ (step.confidence * 100).toFixed(0) }}%</span>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
</div>
|
|
|
<template v-if="message.role === 'user' && message.files">
|
|
@@ -645,7 +678,7 @@
|
|
|
<div class="option reply" :class="{ 'open': isFabOpen }" @click.stop="handleReply">
|
|
|
<i class="material-icons">reply</i>
|
|
|
</div>
|
|
|
- <div class="option love" :class="{ 'open': isFabOpen }" @click.stop="handleLove">
|
|
|
+ <div class="option love" :class="{ 'open': isFabOpen }" @click.stop="handleStepClick">
|
|
|
<i class="material-icons">favorite</i>
|
|
|
</div>
|
|
|
<div class="option delete" :class="{ 'open': isFabOpen }" @click.stop="handleDelete">
|
|
@@ -1020,6 +1053,10 @@ const formatted_data = ref('');
|
|
|
const showSteps = ref(false);
|
|
|
const steps = ref([]);
|
|
|
|
|
|
+// 进度条弹窗相关状态
|
|
|
+const showProgressModal = ref(false);
|
|
|
+const progressList = ref([]);
|
|
|
+
|
|
|
// 推荐问题相关状态
|
|
|
const recommendedQuestions = ref([]);
|
|
|
const showRecommendedQuestions = ref(false);
|
|
@@ -1252,8 +1289,39 @@ const fetchDocumentSummary = async () => {
|
|
|
|
|
|
// 处理步骤点击事件
|
|
|
const handleStepClick = (step) => {
|
|
|
- message.success('操作成功')
|
|
|
- // 这里可以添加点击步骤后的逻辑,比如滚动到对应的步骤位置
|
|
|
+ // 显示进度条弹窗
|
|
|
+ showProgressModal.value = true;
|
|
|
+
|
|
|
+ // 创建新的进度项
|
|
|
+ const newProgress = {
|
|
|
+ id: Date.now(),
|
|
|
+ title: step.description || '处理步骤',
|
|
|
+ value: 0,
|
|
|
+ status: '进行中...'
|
|
|
+ };
|
|
|
+
|
|
|
+ // 添加到进度列表
|
|
|
+ progressList.value.push(newProgress);
|
|
|
+
|
|
|
+ // 模拟进度增长
|
|
|
+ const progressInterval = setInterval(() => {
|
|
|
+ const progressIndex = progressList.value.findIndex(p => p.id === newProgress.id);
|
|
|
+ if (progressIndex !== -1) {
|
|
|
+ progressList.value[progressIndex].value += 5;
|
|
|
+
|
|
|
+ if (progressList.value[progressIndex].value >= 100) {
|
|
|
+ clearInterval(progressInterval);
|
|
|
+ progressList.value[progressIndex].status = '完成';
|
|
|
+ progressList.value[progressIndex].value = 100;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 100);
|
|
|
+};
|
|
|
+
|
|
|
+// 关闭进度弹窗
|
|
|
+const closeProgressModal = () => {
|
|
|
+ showProgressModal.value = false;
|
|
|
+ progressList.value = [];
|
|
|
};
|
|
|
|
|
|
// 修改轮换显示逻辑
|
|
@@ -1769,6 +1837,16 @@ const summaryHtml=ref('')
|
|
|
// 立即处理每条消息
|
|
|
|
|
|
handleSSEMessage(currentEvent || 'message', data);
|
|
|
+ if(currentEvent==='intent_analysis'){
|
|
|
+ // 将思考过程添加到当前AI消息中
|
|
|
+ if (tempAiMessage && data.thinking_process) {
|
|
|
+ tempAiMessage.thinkingSteps = data.thinking_process.map(step => ({
|
|
|
+ type: step.step,
|
|
|
+ content: step.thought,
|
|
|
+ confidence: step.confidence
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ }
|
|
|
if(currentEvent === 'final_summary'){
|
|
|
// 检查summary是否以"无效命令:"开头
|
|
|
if (data.summary && data.summary.startsWith('无效命令:')) {
|
|
@@ -1784,7 +1862,7 @@ const summaryHtml=ref('')
|
|
|
(msg) => msg.id !== tempAiMessage.id
|
|
|
);
|
|
|
|
|
|
- // 创建新的AI消息
|
|
|
+ // 创建新的AI消息
|
|
|
const aiMessage = reactive({
|
|
|
id: Date.now() + 2,
|
|
|
role: "assistant",
|
|
@@ -1792,6 +1870,7 @@ const summaryHtml=ref('')
|
|
|
summaryHtml:data.html_content,
|
|
|
analysis_result:data.analysis_result,
|
|
|
automation_plan:data.automation_plan,
|
|
|
+ thinkingSteps: [], // 保留思考过程tempAiMessage?.thinkingSteps ||
|
|
|
displayContent: "",
|
|
|
audioData: null,
|
|
|
showRecommendedQuestions:showRecommendedQuestions.value || false
|
|
@@ -2885,6 +2964,23 @@ const updateCollapsedState = () => {
|
|
|
clearThinkingSteps();
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+ // 获取思考步骤类型的中文名称
|
|
|
+ const getStepTypeName = (stepType) => {
|
|
|
+ const typeNames = {
|
|
|
+ 'query_understanding': '查询理解',
|
|
|
+ 'context_analysis': '上下文分析',
|
|
|
+ 'data_scope': '数据范围',
|
|
|
+ 'business_value': '业务价值',
|
|
|
+ 'start': '开始',
|
|
|
+ 'text_analysis': '文本分析',
|
|
|
+ 'planning': '规划',
|
|
|
+ 'execution': '执行',
|
|
|
+ 'result': '结果',
|
|
|
+ 'conclusion': '结论'
|
|
|
+ };
|
|
|
+ return typeNames[stepType] || stepType;
|
|
|
+ };
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
@@ -2987,6 +3083,121 @@ const updateCollapsedState = () => {
|
|
|
background-color: #f5f5f5;
|
|
|
}
|
|
|
|
|
|
+/* 进度条弹窗样式 */
|
|
|
+.progress-modal-overlay {
|
|
|
+ position: fixed;
|
|
|
+ bottom: 200px;
|
|
|
+ right: 20px;
|
|
|
+ width: auto;
|
|
|
+ height: auto;
|
|
|
+ background-color: transparent;
|
|
|
+ display: block;
|
|
|
+ z-index: 9999;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-modal {
|
|
|
+ background: white;
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 20px;
|
|
|
+ min-width: 280px;
|
|
|
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
|
|
+ text-align: center;
|
|
|
+ border: 1px solid #e8e8e8;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-modal-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-modal-header h3 {
|
|
|
+ margin: 0;
|
|
|
+ color: #333;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.close-btn {
|
|
|
+ background: none;
|
|
|
+ border: none;
|
|
|
+ font-size: 24px;
|
|
|
+ color: #999;
|
|
|
+ cursor: pointer;
|
|
|
+ padding: 0;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ border-radius: 50%;
|
|
|
+ transition: all 0.2s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.close-btn:hover {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-list {
|
|
|
+ max-height: 300px;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-item {
|
|
|
+ margin-bottom: 16px;
|
|
|
+ padding: 12px;
|
|
|
+ border: 1px solid #f0f0f0;
|
|
|
+ border-radius: 8px;
|
|
|
+ background-color: #fafafa;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-item:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-info {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-title {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-percentage {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-bar-container {
|
|
|
+ width: 100%;
|
|
|
+ height: 6px;
|
|
|
+ background-color: #e8e8e8;
|
|
|
+ border-radius: 3px;
|
|
|
+ overflow: hidden;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-bar {
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(90deg, #1890ff, #40a9ff);
|
|
|
+ border-radius: 3px;
|
|
|
+ transition: width 0.1s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.progress-status {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #999;
|
|
|
+ text-align: right;
|
|
|
+}
|
|
|
+
|
|
|
.dropdown-item i {
|
|
|
margin-right: 8px;
|
|
|
font-size: 14px;
|
|
@@ -6166,17 +6377,63 @@ button,
|
|
|
}
|
|
|
|
|
|
.thinking-steps {
|
|
|
- margin-bottom: 10px;
|
|
|
+ margin-bottom: 15px;
|
|
|
font-size: 12px;
|
|
|
color: #666;
|
|
|
+/* border: 1px solid #e8e8e8; */
|
|
|
+ border-radius: 8px;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+
|
|
|
+ .thinking-steps-header {
|
|
|
+ background: #f8f9fa;
|
|
|
+ padding: 8px 12px;
|
|
|
+ /* border-bottom: 1px solid #e8e8e8; */
|
|
|
+ }
|
|
|
+
|
|
|
+ .thinking-title {
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ font-size: 13px;
|
|
|
}
|
|
|
|
|
|
.thinking-step {
|
|
|
- padding: 4px 8px;
|
|
|
- margin-bottom: 4px;
|
|
|
- border-radius: 4px;
|
|
|
- background: #f5f5f5;
|
|
|
+ /* padding: 8px 12px; */
|
|
|
+ margin-bottom: 0;
|
|
|
+ border-radius: 0;
|
|
|
+/* background: #f5f5f5; */
|
|
|
transition: all 0.3s ease;
|
|
|
+ /* border-bottom: 1px solid #e8e8e8; */
|
|
|
+ }
|
|
|
+
|
|
|
+ .thinking-step:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-content {
|
|
|
+ margin-bottom: 6px;
|
|
|
+ line-height: 1.4;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-meta {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 11px;
|
|
|
+ color: #666;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-type {
|
|
|
+ background: #e3f2fd;
|
|
|
+ color: #1976d2;
|
|
|
+ padding: 2px 6px;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-confidence {
|
|
|
+ color: #666;
|
|
|
}
|
|
|
|
|
|
.thinking-step.start {
|
|
@@ -6203,6 +6460,27 @@ button,
|
|
|
background: #e0f7fa;
|
|
|
font-weight: 500;
|
|
|
}
|
|
|
+
|
|
|
+ /* 新增的思考步骤类型样式 */
|
|
|
+ .thinking-step.query_understanding {
|
|
|
+ background: #e8f5e9;
|
|
|
+ border-left: 3px solid #4caf50;
|
|
|
+ }
|
|
|
+
|
|
|
+ .thinking-step.context_analysis {
|
|
|
+ background: #e3f2fd;
|
|
|
+ border-left: 3px solid #2196f3;
|
|
|
+ }
|
|
|
+
|
|
|
+ .thinking-step.data_scope {
|
|
|
+ background: #fff3e0;
|
|
|
+ border-left: 3px solid #ff9800;
|
|
|
+ }
|
|
|
+
|
|
|
+ .thinking-step.business_value {
|
|
|
+ background: #f3e5f5;
|
|
|
+ border-left: 3px solid #9c27b0;
|
|
|
+ }
|
|
|
.step-header {
|
|
|
position: relative;
|
|
|
display: flex;
|
|
@@ -6882,6 +7160,39 @@ button,
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
+/* 深色主题下的思考步骤样式 */
|
|
|
+.dark-theme .thinking-steps {
|
|
|
+ border-color: #404040;
|
|
|
+ background: #1f1f1f;
|
|
|
+}
|
|
|
+
|
|
|
+.dark-theme .thinking-steps-header {
|
|
|
+ background: #2d2d2d;
|
|
|
+ border-color: #404040;
|
|
|
+}
|
|
|
+
|
|
|
+.dark-theme .thinking-title {
|
|
|
+ color: #e0e0e0;
|
|
|
+}
|
|
|
+
|
|
|
+.dark-theme .thinking-step {
|
|
|
+ background: #2d2d2d;
|
|
|
+ border-color: #404040;
|
|
|
+}
|
|
|
+
|
|
|
+.dark-theme .step-content {
|
|
|
+ color: #e0e0e0;
|
|
|
+}
|
|
|
+
|
|
|
+.dark-theme .step-type {
|
|
|
+ background: #1e3a5f;
|
|
|
+ color: #64b5f6;
|
|
|
+}
|
|
|
+
|
|
|
+.dark-theme .step-confidence {
|
|
|
+ color: #b0b0b0;
|
|
|
+}
|
|
|
+
|
|
|
/* .fab .option.reply {
|
|
|
left: calc((100% / 3) - 3px);
|
|
|
}
|