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://10.17.86.60:8656
# VITE_API_BASE_URL=http://10.17.86.171:8656
# 应用基础路径
VITE_BASE_PATH=/ai/
......
......@@ -65,6 +65,7 @@
<component
:is="item.thinkBoxExpanded ? UpOutlined : DownOutlined"
class="toggle-icon"
v-if="item.thinkingTimeText !== '正在思考中'"
/>
</div>
<div :class="['think-box-content', item.thinkBoxExpanded ? 'expanded' : 'collapsed']"
......
<template>
<div class="chart-container">
<div class="tips">
<div class="tips" v-if="chartData?.description">
{{ chartData?.description }}
</div>
<!-- 图表类型选择器 -->
......@@ -341,6 +341,7 @@ onMounted(() => {
overflow: hidden;
width: 100% !important;
max-width: 100% !important;
border: 1px solid #EBEDF0;
.tips {
margin-bottom: 8px;
font-weight: 500;
......
<template>
<div class="message-chart">
<div class="chart-title">{{ title }}</div>
<!-- <div class="chart-title">{{ title }}</div> -->
<div v-if="isEmpty" class="chart-empty">
<div class="empty-icon">📊</div>
<div class="empty-text">暂无数据</div>
......@@ -243,7 +243,6 @@ const getXAxisConfig = (xAxisData: string[]) => {
interval = 1; // 每2个显示一个标签
} else if (dataLength > 6) {
// 数据项适中时,旋转15度
rotate = 15;
margin = 10;
interval = 1; // 每2个显示一个标签
} else {
......@@ -688,7 +687,7 @@ onUnmounted(() => {
<style scoped>
.message-chart {
margin: 24px 0 16px;
margin: 8px 0 ;
/* 完全自适应,不设置固定高度 */
/* 确保宽度不超过父容器 */
box-sizing: border-box; /* 包含边框和内边距在宽度计算中 */
......
<template>
<div class="message-chart">
<div class="chart-title">{{ title }}</div>
<!-- <div class="chart-title">{{ title }}</div> -->
<div v-if="isEmpty" class="chart-empty">
<div class="empty-icon">📊</div>
<div class="empty-text">暂无数据</div>
......@@ -688,7 +688,7 @@ onUnmounted(() => {
<style scoped>
.message-chart {
margin: 24px 0 16px;
margin:8px 0;
box-sizing: border-box;
}
......
<template>
<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 class="empty-icon">📊</div>
<div class="empty-text">暂无数据</div>
......@@ -153,22 +153,7 @@ const createPieOption = (chartConfig: any) => {
// 按值从大到小排序,确保大块在前
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);
};
......@@ -415,7 +400,7 @@ onUnmounted(() => {
<style scoped>
.pie-chart-container {
margin: 16px 0;
margin: 8px 0;
box-sizing: border-box;
width: 100% !important;
max-width: 100% !important;
......
<template>
<div class="message-chart">
<!-- 表格标题 -->
<div class="table-title">{{ tableTitle }}</div>
<!-- <div class="table-title">{{ tableTitle }}</div> -->
<!-- Ant Design Table -->
<div class="table-container">
<a-table
:columns="tableColumns"
......@@ -11,16 +10,20 @@
size="middle"
:scroll="{ x: 'max-content' }"
:pagination="{
pageSize: 15,
current: paginationState.current,
pageSize: paginationState.pageSize,
pageSizeOptions: ['15', '20', '30'],
total: processedTableData?.length || 0,
showTotal: (total) => `共${total}条记录`,
showSizeChanger: true,
}"
@change="handleTableChange"
class="data-table"
>
<!-- 自定义单元格渲染 -->
<template #bodyCell="{ column, text, record }">
<div :class="getCellClass(column.dataIndex)">
{{ renderCellContent(column.dataIndex, text) || '-' }}
{{ renderCellContent(column.dataIndex, text, record) || '-' }}
</div>
</template>
</a-table>
......@@ -31,10 +34,36 @@
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { computed, ref } from 'vue';
import { Table as ATable } from 'ant-design-vue';
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 {
[key: string]: any;
......@@ -65,25 +94,36 @@ const processedTableData = computed(() => {
// 处理传入完整数据结构的情况
if (Array.isArray(props.tableData.rows)) {
// 过滤掉indexFields中的字段,只保留dimFields和indexFieldsFormat中的字段
// 获取字段配置
const indexFields = props.tableData?.indexFields || [];
const dimFields = props.tableData?.dimFields || [];
const indexFieldsFormat = props.tableData?.indexFieldsFormat || [];
// 需要保留的字段:dimFields + indexFieldsFormat
const fieldsToKeep = [...dimFields, ...indexFieldsFormat];
// 需要显示的字段:dimFields + indexFields
const fieldsToShow = [...dimFields, ...indexFields];
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)) {
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)) {
return props.tableData;
......@@ -94,11 +134,11 @@ const processedTableData = computed(() => {
// 判断列是否为数字列
const isNumericColumn = (header: string) => {
// 使用indexFieldsFormat来判断数字列,而不是indexFields
const indexFieldsFormat = props.tableData?.indexFieldsFormat || [];
// 使用indexFields来判断数字列
const indexFields = props.tableData?.indexFields || [];
// 通过indexFieldsFormat来判断数字列
return indexFieldsFormat.includes(header);
// 通过indexFields来判断数字列
return indexFields.includes(header);
};
// 表格标题
......@@ -114,13 +154,19 @@ const tableTitle = computed(() => {
const tableColumns = computed(() => {
if (processedTableData.value.length === 0) return [];
// 使用过滤后的数据的字段作为表头
// 获取字段配置
const indexFields = props.tableData?.indexFields || [];
// 使用处理后的数据的字段作为表头
const headers = Object.keys(processedTableData.value[0]);
return headers.map(header => {
// 将字段名中的FORMAT后缀去掉
const displayHeader = header.replace(/FORMAT$/, '');
// 判断当前字段是否为indexFields字段
const isIndexField = indexFields.includes(header);
return {
title: displayHeader,
dataIndex: header,
......@@ -129,9 +175,17 @@ const tableColumns = computed(() => {
width: getColumnWidth(header),
ellipsis: true,
sorter: isNumericColumn(header) ? (a, b) => {
const aValue = parseFloat(a[header]);
const bValue = parseFloat(b[header]);
return aValue - bValue;
// 对于indexFields字段,使用存储的原始值进行排序
if (isIndexField && a[header] && a[header].value !== undefined) {
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
};
});
......@@ -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值显示箭头图标
if (isTrendColumn(header)) {
const trendValue = String(value).toLowerCase().trim();
......@@ -205,7 +264,7 @@ const renderCellContent = (header: string, value: any) => {
.message-chart {
width: 100%;
max-width: 100%;
margin: 24px 0 16px;
margin: 0 0 16px;
}
.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