Commit a7ebb5e5 authored by 水玉婷's avatar 水玉婷
Browse files

feat:样式调整

parent 77ae015b
...@@ -7,7 +7,7 @@ VITE_BASE_PATH=/ai/ ...@@ -7,7 +7,7 @@ VITE_BASE_PATH=/ai/
VITE_SSE_PATH=/agentService VITE_SSE_PATH=/agentService
# API基础路径 # API基础路径
VITE_API_BASE_PATH='' VITE_API_BASE_PATH='/pedapi'
# 应用代码 # 应用代码
VITE_APP_CODE=ped.qywx VITE_APP_CODE=ped.qywx
......
...@@ -54,10 +54,6 @@ ...@@ -54,10 +54,6 @@
<!-- 思考过程框 --> <!-- 思考过程框 -->
<div v-if="item.hasThinkBox" class="think-box-wrapper"> <div v-if="item.hasThinkBox" class="think-box-wrapper">
<div :class="['think-box-toggle', item.thinkBoxExpanded ? 'expanded' : 'collapsed']" @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"
/>
<div v-if="item.thinkingTimeText" class="thinking-loading"> <div v-if="item.thinkingTimeText" class="thinking-loading">
<span class="thinking-text">{{ item.thinkingTimeText }}</span> <span class="thinking-text">{{ item.thinkingTimeText }}</span>
<div v-if="item.thinkingTimeText === '正在思考中'" class="loading-dots"> <div v-if="item.thinkingTimeText === '正在思考中'" class="loading-dots">
...@@ -66,6 +62,10 @@ ...@@ -66,6 +62,10 @@
<span class="dot"></span> <span class="dot"></span>
</div> </div>
</div> </div>
<component
:is="item.thinkBoxExpanded ? UpOutlined : DownOutlined"
class="toggle-icon"
/>
</div> </div>
<div :class="['think-box-content', item.thinkBoxExpanded ? 'expanded' : 'collapsed']" <div :class="['think-box-content', item.thinkBoxExpanded ? 'expanded' : 'collapsed']"
v-html="templateService.generateThinkingTemplate(item.thinkContent || '')"></div> v-html="templateService.generateThinkingTemplate(item.thinkContent || '')"></div>
...@@ -171,7 +171,10 @@ const currentBlockIndex = ref(-1); ...@@ -171,7 +171,10 @@ const currentBlockIndex = ref(-1);
const hasStartedConversation = ref(false); // 添加对话开始状态 const hasStartedConversation = ref(false); // 添加对话开始状态
// SSE消息处理函数 // SSE消息处理函数
const handleSSEMessage = (data: SSEData) => { const handleSSEMessage = (data: SSEData, isSimulated: boolean = false) => {
if (isSimulated) {
loading.value = false
}
try { try {
console.log('Received SSE message:', data); console.log('Received SSE message:', data);
...@@ -357,18 +360,6 @@ const sendMessage = async (type: MessageType = 'text', params: MessageParams = { ...@@ -357,18 +360,6 @@ const sendMessage = async (type: MessageType = 'text', params: MessageParams = {
// 开始对话 // 开始对话
startConversation(); startConversation();
// 检查SSE连接状态,如果连接断开则触发重连
const connectionState = sseService.getConnectionState();
console.log('SSE连接状态:', connectionState);
// EventSource readyState: 0=CONNECTING, 1=OPEN, 2=CLOSED
if (connectionState === 2) { // 连接已关闭
console.log('💡 检测到SSE连接已断开,触发重连');
if (dialogSessionId.value) {
sseService.reconnectSSE(dialogSessionId.value);
}
}
isAIResponding.value = false; isAIResponding.value = false;
isInThinkingMode.value = false; isInThinkingMode.value = false;
currentAIResponse.value = null; currentAIResponse.value = null;
...@@ -421,6 +412,21 @@ const sendMessage = async (type: MessageType = 'text', params: MessageParams = { ...@@ -421,6 +412,21 @@ const sendMessage = async (type: MessageType = 'text', params: MessageParams = {
await nextTick(); await nextTick();
scrollToBottom(); scrollToBottom();
// 检查SSE连接状态,如果连接断开或连接中则触发重连
const connectionState = sseService.getConnectionState();
console.log('SSE连接状态:', connectionState);
// EventSource readyState: 0=CONNECTING, 1=OPEN, 2=CLOSED
if (connectionState === 2) { // 连接已关闭
sseService.reconnectSSE(dialogSessionId.value);
const simulatedMessage = {
message: '检测到SSE连接错误,触发重连',
status: -1, // 错误状态
type: 0 // 错误类型
};
// 调用handleSSEMessage处理模拟消息
return handleSSEMessage(simulatedMessage, true);
}
try { try {
// 调用外部传入的消息发送函数 // 调用外部传入的消息发送函数
......
<template> <template>
<div class="chart-container"> <div class="chart-container">
<div class="tips">
我是一段描述文字,用于介绍图表数据。
</div>
<!-- 图表类型选择器 --> <!-- 图表类型选择器 -->
<div class="chart-controls"> <div class="chart-controls">
<div class="chart-type-selector"> <div class="chart-type-selector">
...@@ -329,13 +332,16 @@ onMounted(() => { ...@@ -329,13 +332,16 @@ onMounted(() => {
}); });
</script> </script>
<style scoped> <style lang="less" scoped>
.chart-container { .chart-container {
border-radius: 8px; border-radius: 8px;
background-color: #fff; background-color: #fff;
overflow: hidden; overflow: hidden;
width: 100% !important; width: 100% !important;
max-width: 100% !important; max-width: 100% !important;
.tips {
margin-bottom: 8px;
}
} }
.chart-controls { .chart-controls {
......
...@@ -12,23 +12,21 @@ ...@@ -12,23 +12,21 @@
:scroll="{ x: 'max-content' }" :scroll="{ x: 'max-content' }"
:pagination="{ :pagination="{
pageSize: 15, pageSize: 15,
total: processedTableData.value?.length || 0 total: processedTableData?.length || 0,
showTotal: (total) => `共${total}条记录`,
}" }"
class="data-table" class="data-table"
> >
<!-- 自定义单元格渲染 --> <!-- 自定义单元格渲染 -->
<template #bodyCell="{ column, text, record }"> <template #bodyCell="{ column, text, record }">
<div :class="getCellClass(column.dataIndex)"> <div :class="getCellClass(column.dataIndex)">
{{ renderCellContent(column.dataIndex, text) }} {{ renderCellContent(column.dataIndex, text) || '-' }}
</div> </div>
</template> </template>
</a-table> </a-table>
</div> </div>
<!-- 表格页脚 -->
<div v-if="showFooter" class="table-footer">
<span>{{ processedTableData?.length || 0 }}</span> 条记录
</div>
</div> </div>
</template> </template>
...@@ -43,7 +41,6 @@ interface TableData { ...@@ -43,7 +41,6 @@ interface TableData {
} }
interface TableConfig { interface TableConfig {
showFooter?: boolean;
title?: string; title?: string;
} }
...@@ -55,7 +52,6 @@ interface Props { ...@@ -55,7 +52,6 @@ interface Props {
// 组件属性定义 // 组件属性定义
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
config: () => ({ config: () => ({
showFooter: true,
title: '数据表格', title: '数据表格',
dimFields: [], dimFields: [],
indexFields: [] indexFields: []
...@@ -84,10 +80,6 @@ const tableTitle = computed(() => { ...@@ -84,10 +80,6 @@ const tableTitle = computed(() => {
return props.config.title || '数据表格'; return props.config.title || '数据表格';
}); });
// 是否显示页脚
const showFooter = computed(() => {
return props.config.showFooter !== false;
});
// 获取表头列配置 // 获取表头列配置
const tableColumns = computed(() => { const tableColumns = computed(() => {
...@@ -119,6 +111,15 @@ const isNumericColumn = (header: string) => { ...@@ -119,6 +111,15 @@ const isNumericColumn = (header: string) => {
return indexFields.includes(header); return indexFields.includes(header);
}; };
// 判断是否为文本列
const isTextColumn = (header: string) => {
// 直接从传入的数据中获取dimFields
const dimFields = props.tableData?.dimFields || [];
// 只通过dimFields来判断文本列
return dimFields.includes(header);
};
// 判断列是否为趋势列 // 判断列是否为趋势列
const isTrendColumn = (header: string) => { const isTrendColumn = (header: string) => {
return header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend'); return header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend');
...@@ -130,8 +131,10 @@ const getColumnAlign = (header: string) => { ...@@ -130,8 +131,10 @@ const getColumnAlign = (header: string) => {
return 'center'; return 'center';
} else if (isNumericColumn(header)) { } else if (isNumericColumn(header)) {
return 'right'; return 'right';
} else { } else if (isTextColumn(header)) {
return 'left'; return 'left';
} else {
return 'center';
} }
}; };
...@@ -200,7 +203,6 @@ const renderCellContent = (header: string, value: any) => { ...@@ -200,7 +203,6 @@ const renderCellContent = (header: string, value: any) => {
width: 100%; width: 100%;
overflow-x: auto; overflow-x: auto;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
border-bottom: 1px solid #f0f0f0;
} }
.data-table { .data-table {
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
@gray-5: #999999; @gray-5: #999999;
@gray-6: #666666; @gray-6: #666666;
@gray-7: #323232; @gray-7: #323232;
@gray-8:#646566;
@gray-9:#222629;
@success-color: #52c41a; @success-color: #52c41a;
@error-color: #f5222d; @error-color: #f5222d;
@warning-color: #faad14; @warning-color: #faad14;
...@@ -134,11 +136,10 @@ li { ...@@ -134,11 +136,10 @@ li {
// 聊天头部样式 // 聊天头部样式
.chat-header { .chat-header {
display: flex; display: flex;
justify-content: center;
align-items: center; align-items: center;
border-bottom: 1px solid #e8f2f1; // 保持灰色系 border-bottom: 1px solid #e8f2f1; // 保持灰色系
background: #FCFCFC; // 保持灰色系 background: #FCFCFC; // 保持灰色系
padding: 10px 20px; padding: 10px 12px;
.header-avatar { .header-avatar {
width: 36px; width: 36px;
...@@ -262,7 +263,6 @@ li { ...@@ -262,7 +263,6 @@ li {
max-width: 100%; max-width: 100%;
} }
} }
.message-content { .message-content {
padding: 10px; padding: 10px;
border-radius: 8px; border-radius: 8px;
...@@ -281,10 +281,12 @@ li { ...@@ -281,10 +281,12 @@ li {
} }
.message.received .message-content { .message.received .message-content {
background-color: @blue-light-1; background-color:none;
border-top-left-radius: 5px; border-top-left-radius: 5px;
color: @gray-7; color: @gray-7;
border: 1px solid @blue-light-3; border: none;
padding: 0;
box-shadow:none;
} }
.message.sent .message-content { .message.sent .message-content {
...@@ -321,7 +323,6 @@ li { ...@@ -321,7 +323,6 @@ li {
// 思考框样式 // 思考框样式
:deep(.think-box-toggle) { :deep(.think-box-toggle) {
color: @primary-color;
cursor: pointer; cursor: pointer;
font-size: 14px; font-size: 14px;
text-decoration: none; text-decoration: none;
...@@ -407,7 +408,7 @@ li { ...@@ -407,7 +408,7 @@ li {
max-height: 20000px; // 设置足够大的高度 max-height: 20000px; // 设置足够大的高度
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
margin-top: 8px; margin: 16px 0;
transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); // 平滑展开 transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94); // 平滑展开
} }
...@@ -423,10 +424,11 @@ li { ...@@ -423,10 +424,11 @@ li {
.think-content { .think-content {
font-size: 14px; font-size: 14px;
color: @gray-5; color: @gray-5;
padding: 12px 0;
opacity: 0; opacity: 0;
transform: translateY(5px); transform: translateY(5px);
transition: opacity 0.3s ease-in-out 0.1s, transform 0.3s ease-in-out 0.1s; transition: opacity 0.3s ease-in-out 0.1s, transform 0.3s ease-in-out 0.1s;
padding-left:8px;
border-left: 1px solid #C8C9CC;
} }
&.expanded .think-content { &.expanded .think-content {
...@@ -884,12 +886,12 @@ li { ...@@ -884,12 +886,12 @@ li {
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05); box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0;
position: relative; position: relative;
background-color: @blue-light-2; background-color: @blue-light-2;
border-bottom: 1px solid @blue-light-3; border-bottom: 1px solid @blue-light-3;
font-size: 14px; font-size: 14px;
color: @gray-7; color: @gray-7;
font-weight: 500; font-weight: 500;
line-height: 1.4; line-height: 1.4;
} }
.message-inner-box:has(.message-tips) + .message-inner-box :deep(.message-markdown) { .message-inner-box:has(.message-tips) + .message-inner-box :deep(.message-markdown) {
margin: -1px 0 8px ; margin: -1px 0 8px ;
...@@ -904,17 +906,17 @@ li { ...@@ -904,17 +906,17 @@ li {
max-width: 100%; max-width: 100%;
margin:8px 0; margin:8px 0;
border-radius:8px; border-radius:8px;
background-color: @white; // background-color: @white;
border: 1px solid @blue-light-3; // border: 1px solid @blue-light-3;
border-top: 1px solid @blue-light-3; // border-top: 1px solid @blue-light-3;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); // box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden; overflow: hidden;
.markdown-content { .markdown-content {
padding: 12px 16px; // padding: 12px 16px;
font-size: 14px; font-size: 14px;
line-height: 1.6; line-height: 1.6;
color: @gray-7; color: @gray-9;
background: none; background: none;
white-space: initial; white-space: initial;
...@@ -927,7 +929,7 @@ li { ...@@ -927,7 +929,7 @@ li {
h6 { h6 {
margin-bottom: 8px; margin-bottom: 8px;
font-weight: 600; font-weight: 600;
color: @gray-7; color: @gray-9;
line-height: 1.3; line-height: 1.3;
background: none; background: none;
} }
...@@ -986,7 +988,7 @@ li { ...@@ -986,7 +988,7 @@ li {
code { code {
background: none; background: none;
padding: 0; padding: 0;
color: @gray-7; color: @gray-9;
font-size: 13px; font-size: 13px;
line-height: 1.4; line-height: 1.4;
} }
...@@ -1207,7 +1209,6 @@ li { ...@@ -1207,7 +1209,6 @@ li {
:deep(.message-markdown) { :deep(.message-markdown) {
.markdown-content { .markdown-content {
font-size: 13px; font-size: 13px;
padding: 10px 12px;
h1 { h1 {
font-size: 18px; font-size: 18px;
......
...@@ -398,7 +398,7 @@ export class ContentTemplateService { ...@@ -398,7 +398,7 @@ export class ContentTemplateService {
updatedBlockIndex = updatedResponse.contentBlocks.length; updatedBlockIndex = updatedResponse.contentBlocks.length;
updatedResponse.contentBlocks.push({ updatedResponse.contentBlocks.push({
content: '', content: '',
thinkContent: messageContent ? `${messageContent}` : '正在分析您的问题...', thinkContent: messageContent ? `${messageContent}` : '',
hasThinkBox: true, hasThinkBox: true,
thinkBoxExpanded: false, thinkBoxExpanded: false,
thinkingTime: 0, thinkingTime: 0,
......
...@@ -51,7 +51,7 @@ export class SSEService { ...@@ -51,7 +51,7 @@ export class SSEService {
// 初始化SSE连接 // 初始化SSE连接
public initSSE(dialogSessionId: string): void { public initSSE(dialogSessionId: string): void {
try { try {
const url = `${this.config.apiBaseUrl}${import.meta.env.VITE_SSE_PATH}/sse/join/${this.config.params?.stage || ''}?app-id=${this.config.params?.appId || ''}&dialog-session-id=${dialogSessionId || ''}`; const url = `${import.meta.env.VITE_SSE_PATH}/sse/join/${this.config.params?.stage || ''}?app-id=${this.config.params?.appId || ''}&dialog-session-id=${dialogSessionId || ''}`;
this.eventSource = new EventSourcePolyfill(url, { this.eventSource = new EventSourcePolyfill(url, {
headers: { headers: {
Token: this.config.token || '', Token: this.config.token || '',
......
...@@ -13,40 +13,44 @@ export const formatNumber = (value: any): string => { ...@@ -13,40 +13,44 @@ export const formatNumber = (value: any): string => {
const num = parseFloat(value); const num = parseFloat(value);
if (isNaN(num)) return value; if (isNaN(num)) return value;
if (num >= 100000000) { // 处理负数
const isNegative = num < 0;
const absNum = Math.abs(num);
if (absNum >= 100000000) {
// 亿级别 // 亿级别
const result = num / 100000000; const result = absNum / 100000000;
const decimalPart = result % 1; const decimalPart = result % 1;
if (decimalPart === 0) { if (decimalPart === 0) {
return result.toString() + '亿'; return (isNegative ? '-' : '') + result.toString() + '亿';
} else { } else {
// 最多保留两位小数 // 最多保留两位小数
const fixedResult = result.toFixed(2); const fixedResult = result.toFixed(2);
// 移除末尾的0 // 移除末尾的0
return fixedResult.replace(/\.?0+$/, '') + '亿'; return (isNegative ? '-' : '') + fixedResult.replace(/\.?0+$/, '') + '亿';
} }
} else if (num >= 10000) { } else if (absNum >= 10000) {
// 万级别 // 万级别
const result = num / 10000; const result = absNum / 10000;
const decimalPart = result % 1; const decimalPart = result % 1;
if (decimalPart === 0) { if (decimalPart === 0) {
return result.toString() + ''; return (isNegative ? '-' : '') + result.toString() + '';
} else { } else {
// 最多保留两位小数 // 最多保留两位小数
const fixedResult = result.toFixed(2); const fixedResult = result.toFixed(2);
// 移除末尾的0 // 移除末尾的0
return fixedResult.replace(/\.?0+$/, '') + ''; return (isNegative ? '-' : '') + fixedResult.replace(/\.?0+$/, '') + '';
} }
} else { } else {
// 小于万 // 小于万
const decimalPart = num % 1; const decimalPart = absNum % 1;
if (decimalPart === 0) { if (decimalPart === 0) {
return num.toString(); return (isNegative ? '-' : '') + absNum.toString();
} else { } else {
// 最多保留两位小数 // 最多保留两位小数
const fixedResult = num.toFixed(2); const fixedResult = absNum.toFixed(2);
// 移除末尾的0 // 移除末尾的0
return fixedResult.replace(/\.?0+$/, ''); return (isNegative ? '-' : '') + fixedResult.replace(/\.?0+$/, '');
} }
} }
}; };
......
...@@ -29,20 +29,20 @@ export default defineConfig(({ mode }) => { ...@@ -29,20 +29,20 @@ export default defineConfig(({ mode }) => {
] ]
}, },
proxy: { proxy: {
// // 同时配置两种路径的代理 // 同时配置两种路径的代理
// '/pedapi': { '/pedapi': {
// target: apiBaseUrl, target: apiBaseUrl,
// changeOrigin: true, changeOrigin: true,
// secure: false, secure: false,
// configure: (proxy, options) => { configure: (proxy, options) => {
// proxy.on('error', (err, req, res) => { proxy.on('error', (err, req, res) => {
// console.log('代理错误:', err); console.log('代理错误:', err);
// }); });
// proxy.on('proxyReq', (proxyReq, req, res) => { proxy.on('proxyReq', (proxyReq, req, res) => {
// console.log('发送请求到:', options.target); console.log('发送请求到:', options.target);
// }); });
// } }
// }, },
[agentPath]: { [agentPath]: {
target: apiBaseUrl, target: apiBaseUrl,
changeOrigin: true, changeOrigin: 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