一、项目背景
本文基于若依框架(RuoYi v3.9.1)进行二次开发,实现表格列的按需显示功能。若依框架是一个基于SpringBoot+Vue3前后端分离的Java快速开发框架,前端技术栈采用Vue3 + Element Plus + Vite。
技术栈版本信息
- 框架版本:RuoYi v3.9.1
- Vue版本:3.5.16
- Element Plus版本:2.10.7
- Vite版本:6.3.5
二、问题描述
在若依框架的优惠券管理模块中,默认显示所有表格列,包括序号、优惠券名称、面值、有效期开始、有效期结束、状态、使用说明等。但在实际业务场景中,用户可能只需要关注部分字段,过多的列会影响表格的可读性和用户体验。
参考若依框架内置的用户管理页面,发现该页面已经实现了表格列的按需显示功能,用户可以通过右上角的列配置按钮自由选择要显示的列。因此,我们需要在优惠券管理页面中实现相同的功能。
三、解决方案
通过分析用户管理页面的实现方式,我们发现若依框架已经内置了列显示/隐藏的组件RightToolbar,只需要进行以下三步改造:
- 在
RightToolbar组件中传入columns属性 - 定义列配置对象
columns - 为每个表格列添加
v-if条件控制显示/隐藏
四、实现步骤
步骤1:修改RightToolbar组件,传入columns属性
在优惠券管理页面的工具栏区域,找到right-toolbar组件,添加:columns="columns"属性。
修改位置:src/views/feature/coupon/index.vue 第92行
修改前:
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
修改后:
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
步骤2:定义columns响应式对象
在script setup部分,定义columns响应式对象,配置每个列的标签和显示状态。
修改位置:src/views/feature/coupon/index.vue 第187-193行
添加代码:
const columns = ref({
couponName: { label: '优惠券名称', visible: true },
couponValue: { label: '面值', visible: true },
startTime: { label: '有效期开始', visible: true },
endTime: { label: '有效期结束', visible: true },
status: { label: '状态', visible: true },
remark: { label: '使用说明', visible: true }
})
说明:
- 每个属性对应一个表格列的key
label属性用于在列配置面板中显示列名visible属性控制列的默认显示状态(true为显示,false为隐藏)
步骤3:为表格列添加v-if条件
为每个需要控制显示/隐藏的表格列添加v-if条件,绑定到columns对象中对应列的visible属性。
修改位置:src/views/feature/coupon/index.vue 第97-115行
修改前:
<el-table-column label="优惠券名称" align="center" prop="couponName" />
<el-table-column label="面值" align="center" prop="couponValue" />
<el-table-column label="有效期开始" align="center" prop="startTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="有效期结束" align="center" prop="endTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="common_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="使用说明" align="center" prop="remark" />
修改后:
<el-table-column label="优惠券名称" align="center" prop="couponName" v-if="columns.couponName.visible" />
<el-table-column label="面值" align="center" prop="couponValue" v-if="columns.couponValue.visible" />
<el-table-column label="有效期开始" align="center" prop="startTime" width="180" v-if="columns.startTime.visible">
<template #default="scope">
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="有效期结束" align="center" prop="endTime" width="180" v-if="columns.endTime.visible">
<template #default="scope">
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" v-if="columns.status.visible">
<template #default="scope">
<dict-tag :options="common_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="使用说明" align="center" prop="remark" v-if="columns.remark.visible" />
注意:
- 序号列和操作列不需要添加
v-if条件,因为它们应该始终显示 - 复选框列(type="selection")也不需要添加
v-if条件
五、完整代码示例
以下是优惠券管理页面的完整代码,重点标注了修改部分:
<template>
<div class="app-container">
<!-- 搜索表单区域 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="88px">
<!-- ... 搜索表单内容 ... -->
</el-form>
<!-- 操作按钮栏 -->
<el-row :gutter="10" class="mb8">
<!-- ... 操作按钮 ... -->
<!-- 修改点1:添加columns属性 -->
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<!-- 数据表格 -->
<el-table v-loading="loading" :data="couponList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" align="center" width="80" :index="indexMethod" />
<!-- 修改点2:为每个列添加v-if条件 -->
<el-table-column label="优惠券名称" align="center" prop="couponName" v-if="columns.couponName.visible" />
<el-table-column label="面值" align="center" prop="couponValue" v-if="columns.couponValue.visible" />
<el-table-column label="有效期开始" align="center" prop="startTime" width="180" v-if="columns.startTime.visible">
<template #default="scope">
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="有效期结束" align="center" prop="endTime" width="180" v-if="columns.endTime.visible">
<template #default="scope">
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" v-if="columns.status.visible">
<template #default="scope">
<dict-tag :options="common_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="使用说明" align="center" prop="remark" v-if="columns.remark.visible" />
<!-- 操作列始终显示 -->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['feature:coupon:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['feature:coupon:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
<!-- ... 对话框内容 ... -->
</el-dialog>
</div>
</template>
<script setup name="Coupon">
import { listCoupon, getCoupon, delCoupon, addCoupon, updateCoupon } from "@/api/feature/coupon"
const { proxy } = getCurrentInstance()
const { common_status } = proxy.useDict('common_status')
// 修改点3:定义columns响应式对象
const columns = ref({
couponName: { label: '优惠券名称', visible: true },
couponValue: { label: '面值', visible: true },
startTime: { label: '有效期开始', visible: true },
endTime: { label: '有效期结束', visible: true },
status: { label: '状态', visible: true },
remark: { label: '使用说明', visible: true }
})
const couponList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
couponName: null,
couponValue: null,
startTime: null,
endTime: null,
status: null,
},
rules: {
}
})
const { queryParams, form, rules } = toRefs(data)
/** 序号计算方法 */
function indexMethod(index) {
return (queryParams.value.pageNum - 1) * queryParams.value.pageSize + index + 1
}
/** 查询优惠券管理列表 */
function getList() {
loading.value = true
listCoupon(queryParams.value).then(response => {
couponList.value = response.rows
total.value = response.total
loading.value = false
})
}
// ... 其他方法 ...
</script>
六、功能说明
实现完成后,优惠券管理页面将具备以下功能:
- 列配置按钮:在表格右上角工具栏中会显示一个列配置图标
- 列显示/隐藏:点击列配置按钮,会弹出列配置面板,用户可以勾选或取消勾选要显示的列
- 实时生效:勾选状态变化后,表格列会立即显示或隐藏,无需刷新页面
- 默认全部显示:所有列默认
visible: true,用户可以根据需要隐藏不需要的列 - 固定列:序号列、复选框列和操作列始终显示,不受列配置控制
七、扩展应用
这个功能可以轻松应用到若依框架的其他列表页面中,只需按照上述三个步骤进行修改:
- 在
right-toolbar组件中添加:columns="columns"属性 - 定义
columns响应式对象,配置需要控制的列 - 为对应的表格列添加
v-if="columns.列名.visible"条件
八、注意事项
- 列名一致性:
columns对象中的属性名必须与表格列的prop属性保持一致 - 默认显示状态:根据业务需求设置
visible的默认值,通常建议默认显示所有列 - 固定列:序号列、复选框列和操作列等关键列不建议添加显示/隐藏控制
- 响应式数据:
columns必须使用ref定义,确保响应式更新
九、总结
通过参考若依框架内置的用户管理页面,我们成功为优惠券管理页面添加了表格列按需显示功能。该实现方式简单高效,充分利用了若依框架已有的组件和功能,避免了重复开发。用户可以根据自己的需求自由选择要显示的列,提升了表格的可读性和用户体验。
这种实现方式具有良好的可复用性和扩展性,可以快速应用到其他类似的列表页面中,是若依框架二次开发中的一个实用技巧。