126 lines
3.8 KiB
Plaintext
126 lines
3.8 KiB
Plaintext
明白你的实际需求是这样的:
|
||
|
||
✅ 你有多个类似的表单表格页面
|
||
结构类似,都是用 <el-table> + <el-table-column> 组成。
|
||
|
||
不想复制粘贴逻辑去控制字段显示与否。
|
||
|
||
✅ 每个账号登录后,后端会返回字段权限控制数组
|
||
例如:
|
||
|
||
json
|
||
复制
|
||
编辑
|
||
["customerName", "companyAccount", "companyAddress"]
|
||
你希望根据这个字段列表来自动控制每一列是否显示,不再手动加 v-if="showField('xxx')"。
|
||
|
||
✅ 目标:让字段显示/隐藏逻辑封装好,不影响页面使用结构
|
||
你想要的最终效果是:
|
||
|
||
vue
|
||
复制
|
||
编辑
|
||
<!-- 外部写法保持不变,只改 el-table 为 FormTable -->
|
||
<FormTable :data="formData" :visible-fields="visibleFields">
|
||
<el-table-column label="序号" type="index" width="100" />
|
||
|
||
<el-table-column label="单位名称" prop="customerName">
|
||
<!-- 表单结构 -->
|
||
</el-table-column>
|
||
|
||
<el-table-column label="开户账号" prop="companyAccount">
|
||
<!-- 表单结构 -->
|
||
</el-table-column>
|
||
</FormTable>
|
||
✅ 解决方案:封装 FormTable,自动隐藏字段(通过 prop 字段)
|
||
我们只需要在封装组件中 拦截 slot 中的 el-table-column,判断其 prop 是否在权限字段中,不在就不渲染。
|
||
|
||
✅ 封装组件 FormTable.vue
|
||
vue
|
||
复制
|
||
编辑
|
||
<template>
|
||
<el-table :data="data" v-bind="$attrs" class="-mt-10px">
|
||
<component
|
||
v-for="(vnode, index) in filteredColumns"
|
||
:is="vnode"
|
||
:key="index"
|
||
/>
|
||
</el-table>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { useSlots, computed } from 'vue'
|
||
|
||
const props = defineProps<{
|
||
data: any[]
|
||
visibleFields: string[] // 后端返回的字段权限列表
|
||
}>()
|
||
|
||
const slots = useSlots()
|
||
|
||
// 处理 slots 中的 column,仅保留 prop 在 visibleFields 里的
|
||
const filteredColumns = computed(() => {
|
||
const defaultSlot = slots.default?.() || []
|
||
|
||
return defaultSlot.filter((vnode: any) => {
|
||
// 保留不含 prop 的列(如序号/操作列)
|
||
const prop = vnode.props?.prop
|
||
if (!prop) return true
|
||
return props.visibleFields.includes(prop)
|
||
})
|
||
})
|
||
</script>
|
||
✅ 父组件使用方式(完全一样,只加一个 visibleFields)
|
||
vue
|
||
复制
|
||
编辑
|
||
<FormTable :data="formData" :visible-fields="visibleFields">
|
||
<el-table-column label="序号" type="index" width="100" />
|
||
|
||
<el-table-column label="单位名称" prop="customerName">
|
||
<template #default="{ row, $index }">
|
||
<el-form-item :prop="`${$index}.customerName`" :rules="formRules.customerName">
|
||
<el-input v-model="row.customerName" placeholder="请输入单位名称" />
|
||
</el-form-item>
|
||
</template>
|
||
</el-table-column>
|
||
|
||
<el-table-column label="开户账号" prop="companyAccount">
|
||
<template #default="{ row, $index }">
|
||
<el-form-item :prop="`${$index}.companyAccount`" :rules="formRules.companyAccount">
|
||
<el-input v-model="row.companyAccount" placeholder="请输入开户账号" />
|
||
</el-form-item>
|
||
</template>
|
||
</el-table-column>
|
||
|
||
<!-- 操作列不写 prop,自动保留 -->
|
||
<el-table-column label="操作" fixed="right" width="60">
|
||
<template #default="{ $index }">
|
||
<el-button @click="handleDelete($index)" link>—</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</FormTable>
|
||
✅ 后端返回字段控制
|
||
你只需要从后端返回一个字段列表,比如:
|
||
|
||
ts
|
||
复制
|
||
编辑
|
||
const visibleFields = ['customerName', 'companyAccount']
|
||
然后传给 FormTable 即可:
|
||
|
||
vue
|
||
复制
|
||
编辑
|
||
<FormTable :data="formData" :visible-fields="visibleFields">...</FormTable>
|
||
✅ 总结优点
|
||
✅ 只改 <el-table> 为 <FormTable>,其他逻辑不动。
|
||
|
||
✅ 无需手动每列写 v-if。
|
||
|
||
✅ 可根据后端返回字段权限自动显示/隐藏。
|
||
|
||
✅ 支持任意结构(form-item、插槽等)。
|
||
|
||
需要我帮你做完整的 .vue 文件模板或添加分页/loading 也可以继续说。 |