Commit 219e9ed3 authored by 水玉婷's avatar 水玉婷
Browse files

feat:把表格模版抽离,修改表格样式

parent 5f3adbdc
...@@ -26,8 +26,8 @@ ...@@ -26,8 +26,8 @@
stage: 'wechat-demo', stage: 'wechat-demo',
}; };
// const dialogSessionId = '20251028143404893-00045166'; const dialogSessionId = '20251028143404893-00045166';
const dialogSessionId = ''; // const dialogSessionId = '';
const detailData = ref({ const detailData = ref({
title: '国械小智', title: '国械小智',
}); });
......
...@@ -86,41 +86,7 @@ import { SendOutlined, UserOutlined } from '@ant-design/icons-vue'; ...@@ -86,41 +86,7 @@ import { SendOutlined, UserOutlined } from '@ant-design/icons-vue';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import defaultAvatar from '@/assets/logo.png'; import defaultAvatar from '@/assets/logo.png';
import ChartComponent from './ChartComponent.vue'; // 导入独立的图表组件 import ChartComponent from './ChartComponent.vue'; // 导入独立的图表组件
import { tableTemplate } from './tableTemplate'; // 导入表格模板工具
// 定义消息类型 - 更新接口添加图表相关字段
interface Message {
type: 'received' | 'sent';
avatar: string;
recordId: string;
promptTokens: number;
completionTokens: number;
totalTokens: number;
date: string;
customClass?: string;
contentBlocks: {
content: string;
thinkContent?: string;
hasThinkBox: boolean;
thinkBoxExpanded: boolean;
chartData?: any; // 添加图表数据字段
chartType?: number | string; // 添加图表类型字段
}[];
}
interface Token {
value: string;
expire: number;
}
interface SSEData {
message: any;
status: number | string;
}
interface ChatParams {
stage?: string;
appId?: string;
}
// 组件属性 // 组件属性
const props = withDefaults( const props = withDefaults(
...@@ -148,7 +114,7 @@ const props = withDefaults( ...@@ -148,7 +114,7 @@ const props = withDefaults(
}, },
); );
// 内容模板生成器 // 内容模板生成器 - 简化版本,表格功能已抽离
const contentTemplates = { const contentTemplates = {
// 普通文本 // 普通文本
text: (content: string) => { text: (content: string) => {
...@@ -166,114 +132,9 @@ const contentTemplates = { ...@@ -166,114 +132,9 @@ const contentTemplates = {
error: (content: string) => { error: (content: string) => {
return `<div class="message-error">${content}</div>`; return `<div class="message-error">${content}</div>`;
}, },
// 生成表格HTML // 表格模板 - 使用独立的表格模板工具
table: (tableData: any) => { table: (tableData: any) => {
// 处理SSE返回的JSON数组数据 return tableTemplate(tableData);
// tableData 就是SSE消息中的message字段,直接是你提供的JSON数组
const data = Array.isArray(tableData) ? tableData : [];
if (data.length === 0) {
return `<div class="message-table">
<div class="table-title">数据表格</div>
<div class="table-empty">暂无数据</div>
</div>`;
}
// 动态生成表头 - 使用第一条数据的键名
const headers = Object.keys(data[0]);
// 判断列是否为数字列
const isNumericColumn = (header: string) => {
return data.some(row => {
const value = row[header];
return typeof value === 'number' || (!isNaN(parseFloat(value)) && isFinite(value));
});
};
// 数字格式化函数 - 万/亿格式化,保留两位小数,向上取整
const formatNumber = (value: any) => {
if (value === null || value === undefined || value === '') return '';
const num = parseFloat(value);
if (isNaN(num)) return value;
if (num >= 100000000) {
// 亿级别
const result = Math.ceil((num / 100000000) * 100) / 100;
return result.toFixed(2) + '亿';
} else if (num >= 10000) {
// 万级别
const result = Math.ceil((num / 10000) * 100) / 100;
return result.toFixed(2) + '';
} else {
// 小于万
return Math.ceil(num).toString();
}
};
// 处理单元格内容,特别处理趋势列和数字列
const renderCellContent = (header: string, value: any) => {
// 如果是趋势列,根据up/down值显示箭头图标
if (header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend')) {
const trendValue = String(value).toLowerCase().trim();
if (trendValue === 'up' || trendValue === '上升' || trendValue === '上涨') {
return `<span class="trend-up">↑</span>`;
} else if (trendValue === 'down' || trendValue === '下降' || trendValue === '下跌') {
return `<span class="trend-down">↓</span>`;
}
}
// 如果是数字列,进行格式化
if (isNumericColumn(header)) {
return formatNumber(value);
}
// 其他列保持原样
return value;
};
// 判断列是否为趋势列
const isTrendColumn = (header: string) => {
return header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend');
};
// 为不同列类型添加对应的样式类
const getCellClass = (header: string) => {
if (isTrendColumn(header)) {
return 'trend-cell'; // 趋势列居中
} else if (isNumericColumn(header)) {
return 'numeric-cell'; // 数字列右对齐
} else {
return 'text-cell'; // 文字列左对齐
}
};
const tableHTML = `
<div class="message-table">
<div class="table-container">
<table class="data-table">
<thead>
<tr>
${headers.map(header => `<th class="${getCellClass(header)}">${header}</th>`).join('')}
</tr>
</thead>
<tbody>
${data.map(row => `
<tr>
${headers.map(header => `
<td class="${getCellClass(header)}">
${renderCellContent(header, row[header])}
</td>
`).join('')}
</tr>
`).join('')}
</tbody>
</table>
</div>
<div class="table-footer">共 <span>${data.length}</span> 条记录</div>
</div>
`;
return tableHTML;
}, },
// 简化的iframe模板 - 移除全屏功能,设置宽高100%固定 // 简化的iframe模板 - 移除全屏功能,设置宽高100%固定
iframe: (iframeData: any) => { iframe: (iframeData: any) => {
...@@ -304,6 +165,41 @@ const contentTemplates = { ...@@ -304,6 +165,41 @@ const contentTemplates = {
} }
}; };
// 定义消息类型 - 更新接口添加图表相关字段
interface Message {
type: 'received' | 'sent';
avatar: string;
recordId: string;
promptTokens: number;
completionTokens: number;
totalTokens: number;
date: string;
customClass?: string;
contentBlocks: {
content: string;
thinkContent?: string;
hasThinkBox: boolean;
thinkBoxExpanded: boolean;
chartData?: any; // 添加图表数据字段
chartType?: number | string; // 添加图表类型字段
}[];
}
interface Token {
value: string;
expire: number;
}
interface SSEData {
message: any;
status: number | string;
}
interface ChatParams {
stage?: string;
appId?: string;
}
// 响应式数据 // 响应式数据
const messageText = ref(''); const messageText = ref('');
const messages = ref<Message[]>([]); const messages = ref<Message[]>([]);
......
...@@ -480,18 +480,19 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{ ...@@ -480,18 +480,19 @@ p,h1,h2,h3,h4,h5,h6,ul,ol,li{
text-overflow: ellipsis; text-overflow: ellipsis;
vertical-align: middle; // 确保内容垂直居中 vertical-align: middle; // 确保内容垂直居中
min-width: 80px; // 设置最小列宽,与表头保持一致 min-width: 80px; // 设置最小列宽,与表头保持一致
}
&:nth-child(odd) {
background-color: #f8faff; // 修改奇数行背景色为浅蓝色 // 将奇偶行背景色设置移动到tr元素上
} tr:nth-child(odd) td {
background-color: #f8faff; // 奇数行背景色为浅蓝色
&:nth-child(even) { }
background-color: white;
} tr:nth-child(even) td {
background-color: white; // 偶数行背景色为白色
} }
tr:hover td { tr:hover td {
background-color: #e8f6f4; background-color: #f0f5ff; // 修改为蓝色系的悬停背景色
} }
tr:last-child td { tr:last-child td {
......
/**
* 表格模板工具类
* 用于生成和渲染数据表格
*/
// 表格数据接口
export interface TableData {
[key: string]: any;
}
// 表格配置接口
export interface TableConfig {
showFooter?: boolean;
}
/**
* 生成表格HTML
* @param tableData 表格数据数组
* @param config 表格配置
* @returns 表格HTML字符串
*/
export const generateTableHTML = (tableData: TableData[], config: TableConfig = {}): string => {
const { showFooter = true } = config;
// 处理空数据
if (!Array.isArray(tableData) || tableData.length === 0) {
return `
<div class="message-table">
<div class="table-title">数据表格</div>
<div class="table-empty">暂无数据</div>
</div>`;
}
// 动态生成表头 - 使用第一条数据的键名
const headers = Object.keys(tableData[0]);
// 判断列是否为数字列
const isNumericColumn = (header: string) => {
return tableData.some(row => {
const value = row[header];
return typeof value === 'number' || (!isNaN(parseFloat(value)) && isFinite(value));
});
};
// 数字格式化函数 - 万/亿格式化,保留两位小数,向上取整
const formatNumber = (value: any) => {
if (value === null || value === undefined || value === '') return '';
const num = parseFloat(value);
if (isNaN(num)) return value;
if (num >= 100000000) {
// 亿级别
const result = Math.ceil((num / 100000000) * 100) / 100;
return result.toFixed(2) + '亿';
} else if (num >= 10000) {
// 万级别
const result = Math.ceil((num / 10000) * 100) / 100;
return result.toFixed(2) + '';
} else {
// 小于万
return Math.ceil(num).toString();
}
};
// 处理单元格内容,特别处理趋势列和数字列
const renderCellContent = (header: string, value: any) => {
// 如果是趋势列,根据up/down值显示箭头图标
if (header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend')) {
const trendValue = String(value).toLowerCase().trim();
if (trendValue === 'up' || trendValue === '上升' || trendValue === '上涨') {
return `<span class="trend-up">↑</span>`;
} else if (trendValue === 'down' || trendValue === '下降' || trendValue === '下跌') {
return `<span class="trend-down">↓</span>`;
}
}
// 如果是数字列,进行格式化
if (isNumericColumn(header)) {
return formatNumber(value);
}
// 其他列保持原样
return value;
};
// 判断列是否为趋势列
const isTrendColumn = (header: string) => {
return header.toLowerCase().includes('趋势') || header.toLowerCase().includes('trend');
};
// 为不同列类型添加对应的样式类
const getCellClass = (header: string) => {
if (isTrendColumn(header)) {
return 'trend-cell'; // 趋势列居中
} else if (isNumericColumn(header)) {
return 'numeric-cell'; // 数字列右对齐
} else {
return 'text-cell'; // 文字列左对齐
}
};
return `
<div class="message-table">
<div class="table-container">
<table class="data-table">
<thead>
<tr>
${headers.map(header => `<th class="${getCellClass(header)}">${header}</th>`).join('')}
</tr>
</thead>
<tbody>
${tableData.map(row => `
<tr>
${headers.map(header => `
<td class="${getCellClass(header)}">
${renderCellContent(header, row[header])}
</td>
`).join('')}
</tr>
`).join('')}
</tbody>
</table>
</div>
${showFooter ? `<div class="table-footer">共 <span>${tableData.length}</span> 条记录</div>` : ''}
</div>
`;
};
/**
* 简化的表格生成函数(兼容旧版本)
* @param tableData 表格数据
* @returns 表格HTML字符串
*/
export const tableTemplate = (tableData: any): string => {
return generateTableHTML(tableData);
};
export default {
generateTableHTML,
tableTemplate
};
\ No newline at end of file
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