Commit 1a6bb856 authored by 水玉婷's avatar 水玉婷
Browse files

feat:表格添加排序分页功能及样式调整

parent f377459f
# 开发环境配置 # 开发环境配置
VITE_API_BASE_URL=http://peddev.cmic.com.cn VITE_API_BASE_URL=http://peddev.cmic.com.cn
# VITE_API_BASE_URL=http://10.17.86.60:8656 # VITE_API_BASE_URL=http://10.17.86.60:8656
# VITE_API_BASE_URL=http://10.17.86.171:8656
# 应用基础路径 # 应用基础路径
VITE_BASE_PATH=/ai/ VITE_BASE_PATH=/ai/
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
<component <component
:is="item.thinkBoxExpanded ? UpOutlined : DownOutlined" :is="item.thinkBoxExpanded ? UpOutlined : DownOutlined"
class="toggle-icon" class="toggle-icon"
v-if="item.thinkingTimeText !== '正在思考中'"
/> />
</div> </div>
<div :class="['think-box-content', item.thinkBoxExpanded ? 'expanded' : 'collapsed']" <div :class="['think-box-content', item.thinkBoxExpanded ? 'expanded' : 'collapsed']"
......
<template> <template>
<div class="chart-container"> <div class="chart-container">
<div class="tips"> <div class="tips" v-if="chartData?.description">
{{ chartData?.description }} {{ chartData?.description }}
</div> </div>
<!-- 图表类型选择器 --> <!-- 图表类型选择器 -->
...@@ -341,6 +341,7 @@ onMounted(() => { ...@@ -341,6 +341,7 @@ onMounted(() => {
overflow: hidden; overflow: hidden;
width: 100% !important; width: 100% !important;
max-width: 100% !important; max-width: 100% !important;
border: 1px solid #EBEDF0;
.tips { .tips {
margin-bottom: 8px; margin-bottom: 8px;
font-weight: 500; font-weight: 500;
......
<template> <template>
<div class="message-chart"> <div class="message-chart">
<div class="chart-title">{{ title }}</div> <!-- <div class="chart-title">{{ title }}</div> -->
<div v-if="isEmpty" class="chart-empty"> <div v-if="isEmpty" class="chart-empty">
<div class="empty-icon">📊</div> <div class="empty-icon">📊</div>
<div class="empty-text">暂无数据</div> <div class="empty-text">暂无数据</div>
...@@ -243,7 +243,6 @@ const getXAxisConfig = (xAxisData: string[]) => { ...@@ -243,7 +243,6 @@ const getXAxisConfig = (xAxisData: string[]) => {
interval = 1; // 每2个显示一个标签 interval = 1; // 每2个显示一个标签
} else if (dataLength > 6) { } else if (dataLength > 6) {
// 数据项适中时,旋转15度 // 数据项适中时,旋转15度
rotate = 15;
margin = 10; margin = 10;
interval = 1; // 每2个显示一个标签 interval = 1; // 每2个显示一个标签
} else { } else {
...@@ -688,7 +687,7 @@ onUnmounted(() => { ...@@ -688,7 +687,7 @@ onUnmounted(() => {
<style scoped> <style scoped>
.message-chart { .message-chart {
margin: 24px 0 16px; margin: 8px 0 ;
/* 完全自适应,不设置固定高度 */ /* 完全自适应,不设置固定高度 */
/* 确保宽度不超过父容器 */ /* 确保宽度不超过父容器 */
box-sizing: border-box; /* 包含边框和内边距在宽度计算中 */ box-sizing: border-box; /* 包含边框和内边距在宽度计算中 */
......
<template> <template>
<div class="message-chart"> <div class="message-chart">
<div class="chart-title">{{ title }}</div> <!-- <div class="chart-title">{{ title }}</div> -->
<div v-if="isEmpty" class="chart-empty"> <div v-if="isEmpty" class="chart-empty">
<div class="empty-icon">📊</div> <div class="empty-icon">📊</div>
<div class="empty-text">暂无数据</div> <div class="empty-text">暂无数据</div>
...@@ -688,7 +688,7 @@ onUnmounted(() => { ...@@ -688,7 +688,7 @@ onUnmounted(() => {
<style scoped> <style scoped>
.message-chart { .message-chart {
margin: 24px 0 16px; margin:8px 0;
box-sizing: border-box; box-sizing: border-box;
} }
......
<template> <template>
<div class="pie-chart-container"> <div class="pie-chart-container">
<div class="chart-title">{{ title }}</div> <!-- <div class="chart-title">{{ title }}</div> -->
<div v-if="isEmpty" class="chart-empty"> <div v-if="isEmpty" class="chart-empty">
<div class="empty-icon">📊</div> <div class="empty-icon">📊</div>
<div class="empty-text">暂无数据</div> <div class="empty-text">暂无数据</div>
...@@ -153,22 +153,7 @@ const createPieOption = (chartConfig: any) => { ...@@ -153,22 +153,7 @@ const createPieOption = (chartConfig: any) => {
// 按值从大到小排序,确保大块在前 // 按值从大到小排序,确保大块在前
pieData.sort((a, b) => b.value - a.value); pieData.sort((a, b) => b.value - a.value);
// 如果数据项太多,只显示前10个,其他合并为"其他"
if (pieData.length > 10) {
const top10 = pieData.slice(0, 10);
const othersValue = pieData.slice(10).reduce((sum, item) => sum + item.value, 0);
if (othersValue > 0) {
top10.push({
name: '其他',
value: othersValue
});
}
return createPieChartOption(top10);
}
return createPieChartOption(pieData); return createPieChartOption(pieData);
}; };
...@@ -415,7 +400,7 @@ onUnmounted(() => { ...@@ -415,7 +400,7 @@ onUnmounted(() => {
<style scoped> <style scoped>
.pie-chart-container { .pie-chart-container {
margin: 16px 0; margin: 8px 0;
box-sizing: border-box; box-sizing: border-box;
width: 100% !important; width: 100% !important;
max-width: 100% !important; max-width: 100% !important;
......
<template> <template>
<div class="message-chart"> <div class="message-chart">
<!-- 表格标题 --> <!-- 表格标题 -->
<div class="table-title">{{ tableTitle }}</div> <!-- <div class="table-title">{{ tableTitle }}</div> -->
<!-- Ant Design Table -->
<div class="table-container"> <div class="table-container">
<a-table <a-table
:columns="tableColumns" :columns="tableColumns"
...@@ -11,16 +10,20 @@ ...@@ -11,16 +10,20 @@
size="middle" size="middle"
:scroll="{ x: 'max-content' }" :scroll="{ x: 'max-content' }"
:pagination="{ :pagination="{
pageSize: 15, current: paginationState.current,
pageSize: paginationState.pageSize,
pageSizeOptions: ['15', '20', '30'],
total: processedTableData?.length || 0, total: processedTableData?.length || 0,
showTotal: (total) => `共${total}条记录`, showTotal: (total) => `共${total}条记录`,
showSizeChanger: true,
}" }"
@change="handleTableChange"
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, record) || '-' }}
</div> </div>
</template> </template>
</a-table> </a-table>
...@@ -31,10 +34,36 @@ ...@@ -31,10 +34,36 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed, ref } from 'vue';
import { Table as ATable } from 'ant-design-vue'; import { Table as ATable } from 'ant-design-vue';
import { formatNumber } from './utils/utils'; import { formatNumber } from './utils/utils';
// 分页变化事件
const emit = defineEmits(['paginationChange']);
// 分页状态
const paginationState = ref({
current: 1,
pageSize: 15
});
// 处理表格变化事件(包括分页、排序等)
const handleTableChange = (pagination: any, filters: any, sorter: any) => {
// 处理分页变化
if (pagination) {
// 更新分页状态
paginationState.value = {
current: pagination.current || 1,
pageSize: pagination.pageSize || 15
};
}
// 可以在这里添加排序变化的处理
if (sorter) {
// console.log('排序变化:', sorter);
}
};
// 类型定义 // 类型定义
interface TableData { interface TableData {
[key: string]: any; [key: string]: any;
...@@ -65,25 +94,36 @@ const processedTableData = computed(() => { ...@@ -65,25 +94,36 @@ const processedTableData = computed(() => {
// 处理传入完整数据结构的情况 // 处理传入完整数据结构的情况
if (Array.isArray(props.tableData.rows)) { if (Array.isArray(props.tableData.rows)) {
// 过滤掉indexFields中的字段,只保留dimFields和indexFieldsFormat中的字段 // 获取字段配置
const indexFields = props.tableData?.indexFields || []; const indexFields = props.tableData?.indexFields || [];
const dimFields = props.tableData?.dimFields || []; const dimFields = props.tableData?.dimFields || [];
const indexFieldsFormat = props.tableData?.indexFieldsFormat || []; const indexFieldsFormat = props.tableData?.indexFieldsFormat || [];
// 需要保留的字段:dimFields + indexFieldsFormat // 需要显示的字段:dimFields + indexFields
const fieldsToKeep = [...dimFields, ...indexFieldsFormat]; const fieldsToShow = [...dimFields, ...indexFields];
return props.tableData.rows.map(row => { return props.tableData.rows.map(row => {
const filteredRow: Record<string, any> = {}; const processedRow: Record<string, any> = {};
// 只保留需要的字段 // 处理每个字段
fieldsToKeep.forEach(field => { fieldsToShow.forEach(field => {
if (row.hasOwnProperty(field)) { if (row.hasOwnProperty(field)) {
filteredRow[field] = row[field]; // 如果是indexFields字段,检查是否有对应的indexFieldsFormat字段
const fieldIndex = indexFields.indexOf(field);
if (fieldIndex !== -1 && indexFieldsFormat[fieldIndex] && row.hasOwnProperty(indexFieldsFormat[fieldIndex])) {
// 使用indexFieldsFormat的格式化值来显示,但保留原始值用于排序
processedRow[field] = {
display: row[indexFieldsFormat[fieldIndex]],
value: row[field]
};
} else {
// 其他字段直接使用原始值
processedRow[field] = row[field];
}
} }
}); });
return filteredRow; return processedRow;
}); });
} else if (Array.isArray(props.tableData)) { } else if (Array.isArray(props.tableData)) {
return props.tableData; return props.tableData;
...@@ -94,11 +134,11 @@ const processedTableData = computed(() => { ...@@ -94,11 +134,11 @@ const processedTableData = computed(() => {
// 判断列是否为数字列 // 判断列是否为数字列
const isNumericColumn = (header: string) => { const isNumericColumn = (header: string) => {
// 使用indexFieldsFormat来判断数字列,而不是indexFields // 使用indexFields来判断数字列
const indexFieldsFormat = props.tableData?.indexFieldsFormat || []; const indexFields = props.tableData?.indexFields || [];
// 通过indexFieldsFormat来判断数字列 // 通过indexFields来判断数字列
return indexFieldsFormat.includes(header); return indexFields.includes(header);
}; };
// 表格标题 // 表格标题
...@@ -114,13 +154,19 @@ const tableTitle = computed(() => { ...@@ -114,13 +154,19 @@ const tableTitle = computed(() => {
const tableColumns = computed(() => { const tableColumns = computed(() => {
if (processedTableData.value.length === 0) return []; if (processedTableData.value.length === 0) return [];
// 使用过滤后的数据的字段作为表头 // 获取字段配置
const indexFields = props.tableData?.indexFields || [];
// 使用处理后的数据的字段作为表头
const headers = Object.keys(processedTableData.value[0]); const headers = Object.keys(processedTableData.value[0]);
return headers.map(header => { return headers.map(header => {
// 将字段名中的FORMAT后缀去掉 // 将字段名中的FORMAT后缀去掉
const displayHeader = header.replace(/FORMAT$/, ''); const displayHeader = header.replace(/FORMAT$/, '');
// 判断当前字段是否为indexFields字段
const isIndexField = indexFields.includes(header);
return { return {
title: displayHeader, title: displayHeader,
dataIndex: header, dataIndex: header,
...@@ -129,9 +175,17 @@ const tableColumns = computed(() => { ...@@ -129,9 +175,17 @@ const tableColumns = computed(() => {
width: getColumnWidth(header), width: getColumnWidth(header),
ellipsis: true, ellipsis: true,
sorter: isNumericColumn(header) ? (a, b) => { sorter: isNumericColumn(header) ? (a, b) => {
const aValue = parseFloat(a[header]); // 对于indexFields字段,使用存储的原始值进行排序
const bValue = parseFloat(b[header]); if (isIndexField && a[header] && a[header].value !== undefined) {
return aValue - bValue; const aValue = parseFloat(a[header].value);
const bValue = parseFloat(b[header].value);
return aValue - bValue;
} else {
// 其他字段直接使用当前字段排序
const aValue = parseFloat(a[header]);
const bValue = parseFloat(b[header]);
return aValue - bValue;
}
} : undefined } : undefined
}; };
}); });
...@@ -187,7 +241,12 @@ const getCellClass = (header: string) => { ...@@ -187,7 +241,12 @@ const getCellClass = (header: string) => {
}; };
// 渲染单元格内容 // 渲染单元格内容
const renderCellContent = (header: string, value: any) => { const renderCellContent = (header: string, value: any, record: any) => {
// 处理indexFields字段的特殊数据结构
if (value && typeof value === 'object' && value.display !== undefined) {
value = value.display;
}
// 如果是趋势列,根据up/down值显示箭头图标 // 如果是趋势列,根据up/down值显示箭头图标
if (isTrendColumn(header)) { if (isTrendColumn(header)) {
const trendValue = String(value).toLowerCase().trim(); const trendValue = String(value).toLowerCase().trim();
...@@ -205,7 +264,7 @@ const renderCellContent = (header: string, value: any) => { ...@@ -205,7 +264,7 @@ const renderCellContent = (header: string, value: any) => {
.message-chart { .message-chart {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
margin: 24px 0 16px; margin: 0 0 16px;
} }
.table-title { .table-title {
......
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