动态表格配置

基于 Element Plus 的动态表单配置组件

下面是一个基于 Element Plus 的动态表格配置组件,支持添加多种类型的表单元素,并具有类型互斥、自动计算位数等功能。

组件代码

vue

xml 复制代码
<template>
  <!-- 组件标题 -->
  <h3>动态表单元素配置</h3>
  
  <!-- 添加按钮:最多只能添加4项 -->
  <div class="mb-4">
    <el-button @click="add" :disabled="tableData.length >= 4">
      <el-icon><Plus /></el-icon>
      添加
    </el-button>
  </div>
  
  <!-- 表格展示配置项 -->
  <el-table :data="tableData" border style="width: 100%">
    <!-- 序号列 -->
    <el-table-column type="index" label="序号" width="70" />
    
    <!-- 操作列:删除按钮 -->
    <el-table-column label="操作" width="100">
      <template #default="{ $index }">
        <el-button type="danger" size="small" @click="deleteData($index)">
          <el-icon><Delete /></el-icon>
          删除
        </el-button>
      </template>
    </el-table-column>
    
    <!-- 类型选择列:各类型之间互斥 -->
    <el-table-column prop="type" label="类型" width="180">
      <template #default="{ row, $index }">
        <el-select v-model="row.type" placeholder="请选择" clearable>
          <el-option
            v-for="option in getAvailableOptions($index)"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          ></el-option>
        </el-select>
      </template>
    </el-table-column>
    
    <!-- 内容配置列:根据类型显示不同控件 -->
    <el-table-column prop="content" label="内容" min-width="200">
      <template #default="{ row }">
        <!-- 日期类型:选择日期格式 -->
        <div v-if="row.type === '日期'">
          <el-select v-model="row.content" placeholder="请选择" @change="handleDateContentChange(row)">
            <el-option
              v-for="option in contentOptions"
              :key="option.value"
              :label="option.label"
              :value="option.value"
            ></el-option>
          </el-select>
        </div>
        
        <!-- 固定值类型:输入文本 -->
        <div v-if="row.type === '固定值'">
          <el-input v-model="row.content" @input="handleFixedValueContentChange(row)" placeholder="请输入固定值"></el-input>
        </div>
        
        <!-- 流水号类型:输入数字 -->
        <div v-if="row.type === '流水号'">
          <el-input-number
            style="width: 100%"
            v-model="row.content"
            :controls="false"
            placeholder="从什么数开始"
            :min="0"
          ></el-input-number>
        </div>
        
        <!-- 随机数类型:无需内容配置 -->
        <div v-if="row.type === '随机数'">
          <span class="text-gray-500">自动生成</span>
        </div>
      </template>
    </el-table-column>
    
    <!-- 位数配置列:根据类型决定是否可编辑 -->
    <el-table-column prop="number" label="位数" width="150">
      <template #default="{ row }">
        <el-input-number
          v-model="row.number"
          :controls="false"
          placeholder="请输入位数"
          style="width: 100%"
          :disabled="row.type === '日期' || row.type === '固定值'"
          :min="1"
        ></el-input-number>
      </template>
    </el-table-column>
  </el-table>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import { Plus, Delete } from '@element-plus/icons-vue';

// 表格数据:存储配置的表单元素
const tableData: any = ref([]);

// 所有可选的类型选项
const allOptions = [
  { label: '日期', value: '日期' },
  { label: '固定值', value: '固定值' },
  { label: '随机数', value: '随机数' },
  { label: '流水号', value: '流水号' },
];

// 日期类型的内容选项
const contentOptions = [
  { label: 'YYYYMMDDHHmmss', value: 'YYYYMMDDHHmmss' },
  { label: 'YYYYMMDD', value: 'YYYYMMDD' },
  { label: 'HHmmss', value: 'HHmmss' },
  { label: 'YYYY', value: 'YYYY' },
  { label: 'MM', value: 'MM' },
];

/**
 * 获取当前行可用的类型选项
 * 排除已被其他行选择的类型,实现类型互斥
 * @param currentIndex 当前行索引
 * @returns 可用的类型选项数组
 */
const getAvailableOptions = (currentIndex: number) => {
  // 收集其他行已使用的类型
  const usedTypes = tableData.value
    .map((item: any, index: number) =>
      index !== currentIndex ? item.type : null,
    )
    .filter((type: string) => type);

  // 过滤出可用选项:未被使用,或当前行已选择的类型
  return allOptions.filter(
    (option) =>
      !usedTypes.includes(option.value) ||
      tableData.value[currentIndex]?.type === option.value,
  );
};

/**
 * 处理日期内容变化
 * 自动根据日期格式长度设置位数
 * @param row 当前行数据
 */
const handleDateContentChange = (row: any) => {
  if (row.content) {
    row.number = row.content.length;
  }
};

/**
 * 处理固定值内容变化
 * 自动根据输入的固定值长度设置位数
 * @param row 当前行数据
 */
const handleFixedValueContentChange = (row: any) => {
  if (row.content) {
    row.number = row.content.length;
  } else {
    row.number = 0;
  }
};

/**
 * 添加新的配置项
 * 限制最多添加4项
 */
const add = () => {
  if (tableData.value.length < 4) {
    tableData.value.push({
      type: '',      // 类型
      content: '',   // 内容
      number: 0      // 位数
    });
  }
};

/**
 * 删除指定索引的配置项
 * @param index 要删除的行索引
 */
const deleteData = (index: number) => {
  tableData.value.splice(index, 1);
};
</script>

<style scoped>
.mb-4 {
  margin-bottom: 16px;
}
.text-gray-500 {
  color: #8c8c8c;
}
</style>

组件功能说明

这个动态表单配置组件主要实现了以下功能:

  1. 动态添加 / 删除:支持最多添加 4 个配置项,可随时删除不需要的项

  2. 类型互斥:每种类型(日期 / 固定值 / 随机数 / 流水号)只能使用一次

  3. 类型联动

    • 日期类型:选择预设的日期格式,自动计算位数
    • 固定值类型:输入文本后自动计算位数
    • 流水号类型:设置起始数字,可手动指定位数
    • 随机数类型:无需内容配置,仅需设置位数
  4. 状态控制:根据选择的类型自动禁用 / 启用相关控件

使用场景

该组件适用于需要动态配置编码规则、表单生成规则等场景,例如:

  • 订单编号生成规则配置

  • 报表编号自定义规则

  • 动态表单字段生成配置

通过可视化的方式,用户可以灵活组合不同类型的元素,快速生成符合需求的编码规则。

相关推荐
nlp研究牲4 分钟前
latex中既控制列内容位置又控制列宽,使用>{\centering\arraybackslash}p{0.85cm}
服务器·前端·人工智能·算法·latex
前端拿破轮7 分钟前
HomeBrew创始人都写不出来的翻转二叉树到底怎么做?
前端·算法·typescript
长夜月14 分钟前
React 19 中的新特性
前端
星眠14 分钟前
学习低代码编辑器第三天
前端·面试
VillenK21 分钟前
vban2.0中table的使用
前端·vue.js
Dolphin_海豚25 分钟前
vapor 中的 ast 是如何被 transform 到 IR 的
前端·vue.js·源码
Jimmmmmmm1 小时前
pnpm如何避免幻影依赖:从node_modules演进史说起
前端
拾光拾趣录1 小时前
如何优雅地实现每 5 秒轮询请求?
前端·javascript
snowbitx1 小时前
Vue开发尝试一下
前端
前端缘梦1 小时前
JavaScript 高频面试题精讲:var、let、const 与类型系统全解析
前端·面试