动态表格配置

基于 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. 状态控制:根据选择的类型自动禁用 / 启用相关控件

使用场景

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

  • 订单编号生成规则配置

  • 报表编号自定义规则

  • 动态表单字段生成配置

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

相关推荐
知识分享小能手2 小时前
微信小程序入门学习教程,从入门到精通,微信小程序常用API(上)——知识点详解 + 案例实战(4)
前端·javascript·学习·微信小程序·小程序·html5·微信开放平台
清灵xmf2 小时前
CSS field-sizing 让表单「活」起来
前端·css·field-sizing
文火冰糖的硅基工坊3 小时前
[光学原理与应用-480]:《国产检测设备对比表》
前端·人工智能·系统架构·制造·半导体·产业链
excel3 小时前
Qiankun 子应用生命周期及使用场景解析
前端
weixin_446260853 小时前
Django - 让开发变得简单高效的Web框架
前端·数据库·django
ObjectX前端实验室4 小时前
【react18原理探究实践】异步可中断 & 时间分片
前端·react.js
SoaringHeart4 小时前
Flutter进阶:自定义一个 json 转 model 工具
前端·flutter·dart
努力打怪升级4 小时前
Rocky Linux 8 远程管理配置指南(宿主机 VNC + KVM 虚拟机 VNC)
前端·chrome
brzhang4 小时前
AI Agent 干不好活,不是它笨,告诉你一个残忍的现实,是你给他的工具太难用了
前端·后端·架构
brzhang5 小时前
一文说明白为什么现在 AI Agent 都把重点放在上下文工程(context engineering)上?
前端·后端·架构