Commit 68fb0503 authored by 水玉婷's avatar 水玉婷
Browse files

feat:思考添加动画效果

parent 8c585125
......@@ -53,14 +53,21 @@
<div v-else v-html="item.content" class="message-inner-box"></div>
<!-- 思考过程框 -->
<div v-if="item.hasThinkBox" class="think-box-wrapper">
<div class="think-box-toggle" @click="toggleThinkBox(index, i)">
<div :class="['think-box-toggle', item.thinkBoxExpanded ? 'expanded' : 'collapsed']" @click="toggleThinkBox(index, i)">
<component
:is="item.thinkBoxExpanded ? UpOutlined : DownOutlined"
class="toggle-icon"
/>
<span v-if="item.thinkingTimeText" class="thinking-text">{{ item.thinkingTimeText }}</span>
<div v-if="item.thinkingTimeText" class="thinking-loading">
<span class="thinking-text">{{ item.thinkingTimeText }}</span>
<div v-if="item.thinkingTimeText === '正在思考中'" class="loading-dots">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</div>
</div>
<div v-if="item.thinkBoxExpanded" class="think-box-content"
<div :class="['think-box-content', item.thinkBoxExpanded ? 'expanded' : 'collapsed']"
v-html="templateService.generateThinkingTemplate(item.thinkContent || '')"></div>
</div>
</template>
......@@ -326,17 +333,17 @@ const validateMessageParams = (type: MessageType, params: MessageParams): boolea
// 统一发送消息函数
const sendMessage = async (type: MessageType = 'text', params: MessageParams = {}) => {
// 如果消息文本为空且是文本类型,则延迟1秒后模拟折线图消息进行测试
if (type === 'text' && !messageText.value.trim() && !params.message) {
loading.value = true;
console.log('📊 检测到空消息,1秒后发送折线图测试...');
// if (type === 'text' && !messageText.value.trim() && !params.message) {
// loading.value = true;
// console.log('📊 检测到空消息,1秒后发送折线图测试...');
setTimeout(() => {
simulateLineChartMessage();
loading.value = false;
}, 1000);
// setTimeout(() => {
// simulateLineChartMessage();
// loading.value = false;
// }, 1000);
return;
}
// return;
// }
loading.value = true;
......@@ -589,63 +596,63 @@ onBeforeUnmount(() => {
});
// 模拟折线图消息
const simulateLineChartMessage = () => {
console.log('模拟折线图消息');
// const simulateLineChartMessage = () => {
// console.log('模拟折线图消息');
// 使用真实医院数据创建折线图数据,包含多个维度和指标
const lineChartData = {
title:"2023年各医院月度运营数据汇总",
dimFields: ['月份', '地区', '医院类型', '科室'],
indexFields: ['用户总数', '费用汇总', '平均住院天数', '手术台数', '门诊量'],
rows: [
{ '月份': '1月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 100, '费用汇总': 5000, '平均住院天数': 7.2, '手术台数': 15, '门诊量': 1200 },
{ '月份': '2月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 150, '费用汇总': 6000, '平均住院天数': 6.8, '手术台数': 18, '门诊量': 1400 },
{ '月份': '3月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 120, '费用汇总': 5500, '平均住院天数': 7.5, '手术台数': 16, '门诊量': 1300 },
{ '月份': '4月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 180, '费用汇总': 8000, '平均住院天数': 6.5, '手术台数': 22, '门诊量': 1600 },
{ '月份': '5月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 200, '费用汇总': 9000, '平均住院天数': 6.2, '手术台数': 25, '门诊量': 1800 },
{ '月份': '6月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 250, '费用汇总': 11000, '平均住院天数': 5.8, '手术台数': 30, '门诊量': 2000 },
// // 使用真实医院数据创建折线图数据,包含多个维度和指标
// const lineChartData = {
// title:"2023年各医院月度运营数据汇总",
// dimFields: ['月份', '地区', '医院类型', '科室'],
// indexFields: ['用户总数', '费用汇总', '平均住院天数', '手术台数', '门诊量'],
// rows: [
// { '月份': '1月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 100, '费用汇总': 5000, '平均住院天数': 7.2, '手术台数': 15, '门诊量': 1200 },
// { '月份': '2月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 150, '费用汇总': 6000, '平均住院天数': 6.8, '手术台数': 18, '门诊量': 1400 },
// { '月份': '3月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 120, '费用汇总': 5500, '平均住院天数': 7.5, '手术台数': 16, '门诊量': 1300 },
// { '月份': '4月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 180, '费用汇总': 8000, '平均住院天数': 6.5, '手术台数': 22, '门诊量': 1600 },
// { '月份': '5月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 200, '费用汇总': 9000, '平均住院天数': 6.2, '手术台数': 25, '门诊量': 1800 },
// { '月份': '6月', '地区': '北京', '医院类型': '三甲医院', '科室': '内科', '用户总数': 250, '费用汇总': 11000, '平均住院天数': 5.8, '手术台数': 30, '门诊量': 2000 },
{ '月份': '1月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 80, '费用汇总': 8000, '平均住院天数': 8.5, '手术台数': 45, '门诊量': 800 },
{ '月份': '2月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 120, '费用汇总': 9500, '平均住院天数': 8.2, '手术台数': 52, '门诊量': 900 },
{ '月份': '3月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 100, '费用汇总': 8500, '平均住院天数': 8.8, '手术台数': 48, '门诊量': 850 },
{ '月份': '4月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 150, '费用汇总': 12000, '平均住院天数': 7.8, '手术台数': 60, '门诊量': 1100 },
{ '月份': '5月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 180, '费用汇总': 14000, '平均住院天数': 7.5, '手术台数': 68, '门诊量': 1200 },
{ '月份': '6月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 220, '费用汇总': 16000, '平均住院天数': 7.2, '手术台数': 75, '门诊量': 1400 },
// { '月份': '1月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 80, '费用汇总': 8000, '平均住院天数': 8.5, '手术台数': 45, '门诊量': 800 },
// { '月份': '2月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 120, '费用汇总': 9500, '平均住院天数': 8.2, '手术台数': 52, '门诊量': 900 },
// { '月份': '3月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 100, '费用汇总': 8500, '平均住院天数': 8.8, '手术台数': 48, '门诊量': 850 },
// { '月份': '4月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 150, '费用汇总': 12000, '平均住院天数': 7.8, '手术台数': 60, '门诊量': 1100 },
// { '月份': '5月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 180, '费用汇总': 14000, '平均住院天数': 7.5, '手术台数': 68, '门诊量': 1200 },
// { '月份': '6月', '地区': '北京', '医院类型': '三甲医院', '科室': '外科', '用户总数': 220, '费用汇总': 16000, '平均住院天数': 7.2, '手术台数': 75, '门诊量': 1400 },
{ '月份': '1月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 80, '费用汇总': 4000, '平均住院天数': 6.8, '手术台数': 12, '门诊量': 1000 },
{ '月份': '2月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 120, '费用汇总': 5000, '平均住院天数': 6.5, '手术台数': 15, '门诊量': 1200 },
{ '月份': '3月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 100, '费用汇总': 4500, '平均住院天数': 7.0, '手术台数': 13, '门诊量': 1100 },
{ '月份': '4月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 150, '费用汇总': 7000, '平均住院天数': 6.2, '手术台数': 18, '门诊量': 1400 },
{ '月份': '5月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 180, '费用汇总': 8000, '平均住院天数': 5.9, '手术台数': 22, '门诊量': 1600 },
{ '月份': '6月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 220, '费用汇总': 10000, '平均住院天数': 5.6, '手术台数': 28, '门诊量': 1800 },
// { '月份': '1月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 80, '费用汇总': 4000, '平均住院天数': 6.8, '手术台数': 12, '门诊量': 1000 },
// { '月份': '2月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 120, '费用汇总': 5000, '平均住院天数': 6.5, '手术台数': 15, '门诊量': 1200 },
// { '月份': '3月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 100, '费用汇总': 4500, '平均住院天数': 7.0, '手术台数': 13, '门诊量': 1100 },
// { '月份': '4月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 150, '费用汇总': 7000, '平均住院天数': 6.2, '手术台数': 18, '门诊量': 1400 },
// { '月份': '5月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 180, '费用汇总': 8000, '平均住院天数': 5.9, '手术台数': 22, '门诊量': 1600 },
// { '月份': '6月', '地区': '上海', '医院类型': '三甲医院', '科室': '内科', '用户总数': 220, '费用汇总': 10000, '平均住院天数': 5.6, '手术台数': 28, '门诊量': 1800 },
{ '月份': '1月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 60, '费用汇总': 2500, '平均住院天数': 5.5, '手术台数': 8, '门诊量': 600 },
{ '月份': '2月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 90, '费用汇总': 3200, '平均住院天数': 5.2, '手术台数': 10, '门诊量': 700 },
{ '月份': '3月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 80, '费用汇总': 2800, '平均住院天数': 5.8, '手术台数': 9, '门诊量': 650 },
{ '月份': '4月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 120, '费用汇总': 4500, '平均住院天数': 5.0, '手术台数': 12, '门诊量': 800 },
{ '月份': '5月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 150, '费用汇总': 5500, '平均住院天数': 4.8, '手术台数': 15, '门诊量': 900 },
{ '月份': '6月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 180, '费用汇总': 6500, '平均住院天数': 4.5, '手术台数': 18, '门诊量': 1000 },
// { '月份': '1月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 60, '费用汇总': 2500, '平均住院天数': 5.5, '手术台数': 8, '门诊量': 600 },
// { '月份': '2月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 90, '费用汇总': 3200, '平均住院天数': 5.2, '手术台数': 10, '门诊量': 700 },
// { '月份': '3月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 80, '费用汇总': 2800, '平均住院天数': 5.8, '手术台数': 9, '门诊量': 650 },
// { '月份': '4月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 120, '费用汇总': 4500, '平均住院天数': 5.0, '手术台数': 12, '门诊量': 800 },
// { '月份': '5月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 150, '费用汇总': 5500, '平均住院天数': 4.8, '手术台数': 15, '门诊量': 900 },
// { '月份': '6月', '地区': '上海', '医院类型': '二甲医院', '科室': '内科', '用户总数': 180, '费用汇总': 6500, '平均住院天数': 4.5, '手术台数': 18, '门诊量': 1000 },
{ '月份': '1月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 60, '费用汇总': 3000, '平均住院天数': 6.0, '手术台数': 10, '门诊量': 800 },
{ '月份': '2月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 90, '费用汇总': 4000, '平均住院天数': 5.8, '手术台数': 12, '门诊量': 900 },
{ '月份': '3月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 80, '费用汇总': 3500, '平均住院天数': 6.2, '手术台数': 11, '门诊量': 850 },
{ '月份': '4月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 120, '费用汇总': 6000, '平均住院天数': 5.5, '手术台数': 15, '门诊量': 1100 },
{ '月份': '5月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 150, '费用汇总': 7000, '平均住院天数': 5.2, '手术台数': 18, '门诊量': 1200 },
{ '月份': '6月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 180, '费用汇总': 9000, '平均住院天数': 4.9, '手术台数': 22, '门诊量': 1400 }
],
// chartType: 'line' // 设置默认图表类型为折线图
};
// 正确的SSE消息格式:status 3(图表数据),type 2(表格数据)
const simulatedMessage = {
message: lineChartData,
status: 3, // 图表数据
type: 2 // 表格数据
};
// 调用handleSSEMessage处理模拟消息
handleSSEMessage(simulatedMessage);
};
// { '月份': '1月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 60, '费用汇总': 3000, '平均住院天数': 6.0, '手术台数': 10, '门诊量': 800 },
// { '月份': '2月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 90, '费用汇总': 4000, '平均住院天数': 5.8, '手术台数': 12, '门诊量': 900 },
// { '月份': '3月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 80, '费用汇总': 3500, '平均住院天数': 6.2, '手术台数': 11, '门诊量': 850 },
// { '月份': '4月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 120, '费用汇总': 6000, '平均住院天数': 5.5, '手术台数': 15, '门诊量': 1100 },
// { '月份': '5月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 150, '费用汇总': 7000, '平均住院天数': 5.2, '手术台数': 18, '门诊量': 1200 },
// { '月份': '6月', '地区': '广州', '医院类型': '三甲医院', '科室': '内科', '用户总数': 180, '费用汇总': 9000, '平均住院天数': 4.9, '手术台数': 22, '门诊量': 1400 }
// ],
// // chartType: 'line' // 设置默认图表类型为折线图
// };
// // 正确的SSE消息格式:status 3(图表数据),type 2(表格数据)
// const simulatedMessage = {
// message: lineChartData,
// status: 3, // 图表数据
// type: 2 // 表格数据
// };
// // 调用handleSSEMessage处理模拟消息
// handleSSEMessage(simulatedMessage);
// };
</script>
<style lang="less" scoped>
@import './style.less';
......
......@@ -325,25 +325,113 @@ li {
cursor: pointer;
font-size: 14px;
text-decoration: none;
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
border-radius: 4px;
transition: all 0.2s ease;
gap: 8px;
.toggle-icon {
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
transform: rotate(0deg);
}
// 展开状态下的图标旋转
&.expanded .toggle-icon {
transform: rotate(180deg);
}
.thinking-loading {
display: flex;
align-items: center;
gap: 8px;
}
.loading-dots {
display: flex;
gap: 4px;
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: @primary-color;
animation: loading-dots 1.4s ease-in-out infinite both;
&:nth-child(1) {
animation-delay: -0.32s;
}
&:nth-child(2) {
animation-delay: -0.16s;
}
&:nth-child(3) {
animation-delay: 0s;
}
}
}
.thinking-text {
margin-left: 6px;
color: @gray-7;
font-size: 13px;
transition: color 0.3s ease;
font-weight: 500;
}
}
// Loading dots动画
@keyframes loading-dots {
0%, 80%, 100% {
transform: scale(0.8);
opacity: 0.5;
}
40% {
transform: scale(1.2);
opacity: 1;
}
}
:deep(.think-box-content) {
margin-top: 8px;
overflow: hidden;
max-height: 0;
opacity: 0;
transform: translateY(-10px);
transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.4s ease-in-out,
transform 0.4s ease-in-out,
margin-top 0.4s ease-in-out;
// 展开状态
&.expanded {
max-height: 20000px; // 设置足够大的高度
opacity: 1;
transform: translateY(0);
margin-top: 8px;
transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); // 平滑展开
}
// 折叠状态
&.collapsed {
max-height: 0;
opacity: 0;
transform: translateY(-10px);
margin-top: 0;
transition-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); // 平滑折叠
}
.think-content {
font-size: 14px;
color: @gray-5;
padding: 12px 0;
opacity: 0;
transform: translateY(5px);
transition: opacity 0.3s ease-in-out 0.1s, transform 0.3s ease-in-out 0.1s;
}
&.expanded .think-content {
opacity: 1;
transform: translateY(0);
}
}
......
......@@ -425,7 +425,7 @@ export class ContentTemplateService {
hasThinkBox: true,
thinkBoxExpanded: false,
thinkingTime: 0,
thinkingTimeText: '正在思考中……',
thinkingTimeText: '正在思考中',
});
} else {
// 如果已有思考内容块,确保hasThinkBox为true
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment