页面有个大长表格,需求是方便用户查看数据时方便一些需要根据用户勾选想要查看的列展示在表格中。
显示设置
<!-- 显示设置-->
<a-modal
:visible="state.settingVisible"
title="显示设置"
centered
width="700px"
@ok="confirmSetting"
@cancel="state.settingVisible = false"
:ok-button-props="{
loading: statisticsState.settingLoading
}"
:body-style="{
paddingTop: '0'
}"
>
<a-tabs v-model:activeKey="state.activeKey">
<a-tab-pane key="基础信息" tab="基础信息" />
<a-tab-pane key="时间" tab="时间" />
<a-tab-pane key="其他" tab="其他" />
</a-tabs>
<div v-if="state.activeKey === '时间'">
<a-checkbox-group v-model:value="state.checkList" style="width: 100%">
<a-row>
<a-col :span="6">
<a-checkbox value="计划开始">计划开始时间</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="计划结束">计划结束时间</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="实际开始">实际开始时间</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="实际结束">实际结束时间</a-checkbox>
</a-col>
</a-row>
<a-row style="margin-top: 16px">
<a-col :span="6"> <a-checkbox value="预计开始">预计开始时间</a-checkbox> </a-col
><a-col :span="6">
<a-checkbox value="预计结束">预计结束时间</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
</div>
<div v-if="state.activeKey === '信息统计'">
<a-transfer
:titles="['隐藏', '展示']"
v-model:target-keys="statisticsState.targetKeys"
v-model:selected-keys="statisticsState.selectedKeys"
:data-source="statisticsState.mockData"
:list-style="{
width: '300px',
height: '500px'
}"
:render="item => item.chinessName"
/>
</div>
<div v-if="state.activeKey === '基础信息'">
<a-checkbox-group v-model:value="state.baseCheckList" style="width: 100%">
<a-row>
<a-col :span="6">
<a-checkbox value="批次">批次</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="项目总监">项目总监</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="水泥专家">水泥专家</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="项目经理">项目经理</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="算法">算法</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="商务">商务</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="项目阶段">项目阶段</a-checkbox>
</a-col>
<a-col :span="6">
<a-checkbox value="项目状态">项目状态</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
</div>
</a-modal>
<!-- 显示设置-->
表格部分
<a-table
:columns="filteredColumns"
:dataSource="state.dataSource"
:scroll="{ x: 'max-content', y: state.tableHeight }"
:pagination="false"
:loading="state.tableLoading"
bordered
@resizeColumn="handleResizeColumn"
:showSorterTooltip="false"
@change="handleTableChange"
ref="tableRef"
>
</a-table>
逻辑部分
const filteredColumns = computed(() => {
return columnState.columns
.map(column => {
const updatedColumn = {
...column,
children:
column.children && Array.isArray(column.children)
? column.children.filter(child => child.visible)
: []
}
if (updatedColumn.children.length === 0 && column.children?.length > 0) {
updatedColumn.visible = false
}
return updatedColumn.visible === false ? null : updatedColumn
})
.filter(Boolean)
})
列设置部分,给每一列设置一个visible属性,根据勾选框的值来判断visible的true和false
columns: [
{
title: '序号',
dataIndex: 'count',
align: 'center',
width: 50,
fixed: 'left',
ellipsis: true
},
{
'title': '区域',
'dataIndex': 'areaName',
ellipsis: true,
fixed: 'left',
align: 'center'
},
{
title: '工厂名称',
dataIndex: 'projectShortName',
ellipsis: true,
width: 120,
fixed: 'left',
align: 'center',
customCell: customCellStyle
},
{
title: '批次',
dataIndex: 'batch',
ellipsis: true,
width: 80,
align: 'center',
visible: computed(() => state.baseCheckList.includes('批次'))
},
{
title: '项目总监',
dataIndex: 'projectDirector',
ellipsis: true,
align: 'center',
width: 80,
customCell: customCellStyle,
visible: computed(() => state.baseCheckList.includes('项目总监'))
},
{
title: '水泥专家',
dataIndex: 'businessExpert',
align: 'center',
ellipsis: true,
width: 80,
visible: computed(() => state.baseCheckList.includes('水泥专家'))
},
{
title: '项目经理',
dataIndex: 'pmName',
align: 'center',
ellipsis: true,
width: 80,
customCell: customOkCellStyle,
visible: computed(() => state.baseCheckList.includes('项目经理'))
},
{
title: '算法',
dataIndex: 'algorithmExpert',
align: 'center',
ellipsis: true,
width: 80,
customCell: customOkCellStyle,
visible: computed(() => state.baseCheckList.includes('算法'))
},
{
title: '商务',
dataIndex: 'preSaleManager',
align: 'center',
ellipsis: true,
width: 80,
customCell: customOkCellStyle,
visible: computed(() => state.baseCheckList.includes('商务'))
},
{
title: '数据建模',
ellipsis: true,
align: 'center',
visible: true,
children: [
{
title: '计划开始',
dataIndex: 'modelStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.modelStartTime)
const timeB = dayjs(b.modelStartTime)
// 处理空值,确保空值排在最后
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1 // a 是无效时间,排到后面
if (!timeB.isValid()) return -1 // b 是无效时间,排到后面
// 有效的时间做正常排序
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划开始'))
},
{
title: '计划结束',
dataIndex: 'modelEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.modelEndTime)
const timeB = dayjs(b.modelEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划结束'))
},
{
title: '实际开始',
dataIndex: 'modelActualStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.modelActualStartTime)
const timeB = dayjs(b.modelActualStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际开始'))
},
{
title: '实际结束',
dataIndex: 'modelActualEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.modelActualEndTime)
const timeB = dayjs(b.modelActualEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际结束'))
},
{
title: '预计开始',
dataIndex: 'modelExpectStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.modelExpectStartTime)
const timeB = dayjs(b.modelExpectStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计开始'))
},
{
title: '预计结束',
dataIndex: 'modelExpectEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.modelExpectEndTime)
const timeB = dayjs(b.modelExpectEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计结束'))
}
]
},
{
title: '试运行',
ellipsis: true,
align: 'center',
visible: true,
children: [
{
title: '计划开始',
dataIndex: 'testRunStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.testRunStartTime)
const timeB = dayjs(b.testRunStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划开始'))
},
{
title: '计划结束',
dataIndex: 'testRunEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.testRunEndTime)
const timeB = dayjs(b.testRunEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划结束'))
},
{
title: '实际开始',
dataIndex: 'testRunActualStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.testRunActualStartTime)
const timeB = dayjs(b.testRunActualStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际开始'))
},
{
title: '实际结束',
dataIndex: 'testRunActualEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.testRunActualEndTime)
const timeB = dayjs(b.testRunActualEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际结束'))
},
{
title: '预计开始',
dataIndex: 'testRunExpectStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.testRunExpectStartTime)
const timeB = dayjs(b.testRunExpectStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计开始'))
},
{
title: '预计结束',
dataIndex: 'testRunExpectEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.testRunExpectEndTime)
const timeB = dayjs(b.testRunExpectEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计结束'))
}
]
},
{
title: '正式运行',
ellipsis: true,
align: 'center',
visible: true,
children: [
{
title: '计划开始',
dataIndex: 'runStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.runStartTime)
const timeB = dayjs(b.runStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划开始'))
},
{
title: '计划结束',
dataIndex: 'runEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.runEndTime)
const timeB = dayjs(b.runEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划结束'))
},
{
title: '实际开始',
dataIndex: 'runActualStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.runActualStartTime)
const timeB = dayjs(b.runActualStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际开始'))
},
{
title: '实际结束',
dataIndex: 'runActualEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.runActualEndTime)
const timeB = dayjs(b.runActualEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际结束'))
},
{
title: '预计开始',
dataIndex: 'runExpectStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.runExpectStartTime)
const timeB = dayjs(b.runExpectStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计开始'))
},
{
title: '预计结束',
dataIndex: 'runExpectEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.runExpectEndTime)
const timeB = dayjs(b.runExpectEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计结束'))
}
]
},
{
title: '验证',
ellipsis: true,
align: 'center',
visible: true,
children: [
{
title: '计划开始',
dataIndex: 'verifyStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.verifyStartTime)
const timeB = dayjs(b.verifyStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划开始'))
},
{
title: '计划结束',
dataIndex: 'verifyEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.verifyEndTime)
const timeB = dayjs(b.verifyEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划结束'))
},
{
title: '实际开始',
dataIndex: 'verifyActualStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.verifyActualStartTime)
const timeB = dayjs(b.verifyActualStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际开始'))
},
{
title: '实际结束',
dataIndex: 'verifyActualEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.verifyActualEndTime)
const timeB = dayjs(b.verifyActualEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际结束'))
},
{
title: '预计开始',
dataIndex: 'verifyExpectStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.verifyExpectStartTime)
const timeB = dayjs(b.verifyExpectStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计开始'))
},
{
title: '预计结束',
dataIndex: 'verifyExpectEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.verifyExpectEndTime)
const timeB = dayjs(b.verifyExpectEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计结束'))
}
]
},
{
title: '验收',
ellipsis: true,
align: 'center',
visible: true,
children: [
{
title: '计划开始',
dataIndex: 'checkStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.checkStartTime)
const timeB = dayjs(b.checkStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划开始'))
},
{
title: '计划结束',
dataIndex: 'checkEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.checkEndTime)
const timeB = dayjs(b.checkEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('计划结束'))
},
{
title: '实际开始',
dataIndex: 'checkActualStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.checkActualStartTime)
const timeB = dayjs(b.checkActualStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际开始'))
},
{
title: '实际结束',
dataIndex: 'checkActualEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.checkActualEndTime)
const timeB = dayjs(b.checkActualEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('实际结束'))
},
{
title: '预计开始',
dataIndex: 'checkExpectStartTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.checkExpectStartTime)
const timeB = dayjs(b.checkExpectStartTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计开始'))
},
{
title: '预计结束',
dataIndex: 'checkExpectEndTime',
ellipsis: true,
align: 'center',
width: 150,
sorter: (a, b) => {
const timeA = dayjs(a.checkExpectEndTime)
const timeB = dayjs(b.checkExpectEndTime)
if (!timeA.isValid() && !timeB.isValid()) return 0
if (!timeA.isValid()) return 1
if (!timeB.isValid()) return -1
return timeA - timeB
},
visible: computed(() => state.checkList.includes('预计结束'))
}
]
},
{
title: '项目阶段',
dataIndex: 'milepostName',
sorter: true,
ellipsis: true,
align: 'center',
width: 80,
sorter: true,
visible: computed(() => state.baseCheckList.includes('项目阶段'))
},
{
title: '项目状态',
dataIndex: 'projectStatus',
ellipsis: true,
align: 'center',
width: 80,
visible: computed(() => state.baseCheckList.includes('项目状态'))
},
{
title: '进展',
dataIndex: 'progress',
ellipsis: true,
resizable: true,
align: 'center',
width: 350,
minWidth: 350,
visible: computed(() => state.otherCheckList.includes('进展'))
},
{
title: '问题&风险',
dataIndex: 'question',
ellipsis: true,
align: 'center',
resizable: true,
width: 350,
minWidth: 350,
visible: computed(() => state.otherCheckList.includes('问题风险'))
},
{
title: '风险等级',
dataIndex: 'riskLevel',
align: 'center',
ellipsis: true,
width: 120,
visible: computed(() => state.otherCheckList.includes('风险等级'))
},
{
title: '项目支持',
dataIndex: 'supportors',
align: 'center',
ellipsis: true,
width: 120,
visible: computed(() => state.otherCheckList.includes('项目支持'))
},
{
title: '正式运行持续天数',
dataIndex: 'runDays',
align: 'center',
ellipsis: true,
width: 120,
visible: computed(() => state.otherCheckList.includes('正式运行持续天数'))
},
{
title: '综合样20次',
dataIndex: 'comprehensiveSample',
align: 'center',
ellipsis: true,
width: 120,
visible: computed(() => state.otherCheckList.includes('综合样20次'))
},
{
title: '降本空间',
dataIndex: 'expectedCostReduction',
align: 'center',
ellipsis: true,
width: 120,
visible: computed(() => state.otherCheckList.includes('降本空间'))
},
{
title: '生产计划',
dataIndex: 'productionPlan',
resizable: true,
align: 'center',
ellipsis: true,
width: 350,
minWidth: 350,
visible: computed(() => state.otherCheckList.includes('生产计划'))
},
{
title: '客情关系',
dataIndex: 'customerRelationship',
resizable: true,
align: 'center',
ellipsis: true,
width: 350,
minWidth: 350,
visible: computed(() => state.otherCheckList.includes('客情关系'))
}
// 其他通用列
],