Vue项目-Table添加Form表单校验

一、HTML

html 复制代码
<template>
  <div class="taskInfo">
    <el-form
      :model="generateParams"
      :rules="formRules"
      ref="formRef"
      class="taskInfoForm"
      label-width="100px">
      <ul class="taskInfoSearch">
        <li>
          <el-form-item label="类型" prop="type">
            <el-select
              v-model="generateParams.type"
              placeholder="请选择类型">
              <el-option :value="1" label="aaa"></el-option>
              <el-option :value="2" label="bbb"></el-option>
            </el-select>
          </el-form-item>
        </li>
        <li>
          <el-form-item label="开始" prop="start">
            <el-input
              v-model="generateParams.start"
              placeholder="请输入开始值"></el-input>
          </el-form-item>
        </li>
        <li>
          <el-form-item label="结束" prop="end">
            <el-input
              v-model="generateParams.end"
              placeholder="请输入结束值"></el-input>
          </el-form-item>
        </li>
        <li>
          <el-form-item label="开始时间" prop="startTime">
            <el-date-picker
              v-model="generateParams.startTime"
              type="datetime"
              placeholder="请选择开始时间"
              format="YYYY/MM/DD hh:mm:ss"
              value-format="YYYY-MM-DD h:m:s" />
          </el-form-item>
        </li>
        <li>
          <el-form-item label="结束时间" prop="endTime">
            <el-date-picker
              v-model="generateParams.endTime"
              type="datetime"
              placeholder="请选择结束时间"
              format="YYYY/MM/DD hh:mm:ss"
              value-format="YYYY-MM-DD h:m:s" />
          </el-form-item>
        </li>
      </ul>

      <div class="taskInfoAddBtn">
        <el-button type="primary" @click="addRowData">新增表格数据</el-button>
      </div>

      <div class="taskInfoTab">
        <el-table
          :data="generateParams.studentInfo"
          :cell-class-name="cellClassName"
          :row-class-name="rowClassName"
          @cell-click="cellClick">
          <el-table-column label="姓名">
            <template #default="{ row, column }">
              <el-form-item
                :prop="'studentInfo.' + row.index + '.name'"
                :rules="formRules.name"
                v-if="row.index == rowIndex && column.index == columnIndex">
                <el-input
                  v-model.number="row.name"
                  type="number"
                  @blur="hideInput"
                  v-focus></el-input>
              </el-form-item>
              <span v-else>{{ row.name }}</span>
            </template>
          </el-table-column>
          <el-table-column label="年龄">
            <template #default="{ row, column }">
              <el-form-item
                :prop="'studentInfo.' + row.index + '.age'"
                :rules="formRules.age"
                v-if="row.index == rowIndex && column.index == columnIndex">
                <el-input
                  v-model.number="row.age"
                  type="number"
                  @blur="hideInput"
                  v-focus></el-input>
              </el-form-item>

              <span v-else>{{ row.age }}</span>
            </template>
          </el-table-column>
          <el-table-column label="性别">
            <template #default="{ row, column }">
              <el-form-item
                :prop="'studentInfo.' + row.index + '.sex'"
                :rules="formRules.sex"
                v-if="row.index == rowIndex && column.index == columnIndex">
                <el-input
                  v-model.number="row.sex"
                  type="number"
                  @blur="hideInput"
                  v-focus></el-input>
              </el-form-item>

              <span v-else>{{ row.sex }}</span>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="100">
            <template #default="{ row }">
              <el-button type="danger" link @click="delRowData(row)"
                >删除</el-button
              >
            </template>
          </el-table-column>
        </el-table>
      </div>
    </el-form>

    <div class="generate">
      <el-button type="primary" @click="generate(formRef)"
        >任务信息生成</el-button
      >
    </div>

    <!-- 任务信息生成信息模态框 -->
    <TaskInfoModel ref="TaskInfoModelRef"></TaskInfoModel>
  </div>
</template>

二、JS

javascript 复制代码
<script setup>
// -------------------<<模块引入>>-------------------
import { ref, reactive, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
// -------------------<<变量声明>>-------------------
// 生成参数
const generateParams = reactive({
  type: 1, // 类型
  start: 1000000000, // 开始
  end: 2000000000, // 结束
  startTime: "2024-08-05 15:33:55", // 开始时间
  endTime: "2024-08-15 15:33:55", // 结束时间
  studentInfo: [
    // 任务区域
    {
      name: 123.1122331, // 姓名
      age: 80.12345621, // 年龄
      sex: 1200.1, // 性别
    },
    {
      name: 114.1122331, // 姓名
      age: 80.12345621, // 年龄
      sex: 1200.1, // 性别
    },
    {
      name: 114.1122331, // 姓名
      age: 80.12345621, // 年龄
      sex: 1200.1, // 性别
    },
  ],
});
// form表单规则
const formRules = reactive({
  type: [{ required: true, message: "请选择类型", trigger: "change" }],
  start: [{ required: true, message: "请输入开始", trigger: "blur" }],
  end: [{ required: true, message: "请输入结束", trigger: "blur" }],
  startTime: [{ required: true, message: "请选择开始时间", trigger: "change" }],
  endTime: [{ required: true, message: "请选择结束时间", trigger: "change" }],
  name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
  age: [{ required: true, message: "请输入年龄", trigger: "blur" }],
  sex: [{ required: true, message: "请输入性别", trigger: "blur" }],
});
// 获取form表单ref
const formRef = ref();
// 行列index
const rowIndex = ref(null);
const columnIndex = ref(null);
// 是否允许编辑
const isEdit = ref(true);

// -------------------<<函数定义>>-------------------
// 生成
const generate = (formEl) => {
  if (!formEl) return;
  formEl.validate((valid) => {
    if (valid) {
      console.log(generateParams);
      TaskInfoModelRef.value.openWin();
    } else {
      console.log("error submit!");

      //当验证失败跳转到空白的所在区域
      nextTick(() => {
        let isError = document.getElementsByClassName("is-error");
        isError[0].scrollIntoView({
          // 滚动到指定节点
          // 值有start,center,end,nearest
          block: "center",
          // 值有auto、instant,smooth,缓动动画
          behavior: "smooth",
        });
      });

      return false;
    }
  });
};
// 表格单元格className回调方法
const cellClassName = ({ column, columnIndex }) => {
  column.index = columnIndex;
};
// 表格行className回调方法
const rowClassName = ({ row, rowIndex }) => {
  row.index = rowIndex;
};
// 表格单元格点击事件
const cellClick = (row, column) => {
  if (isEdit.value) {
    rowIndex.value = row.index;
    columnIndex.value = column.index;
  }
};
// input框失去焦点事件
const hideInput = (e) => {
  if (e.target.value) {
    rowIndex.value = null;
    columnIndex.value = null;
    isEdit.value = true;
  } else {
    isEdit.value = false;
  }
};
// 新增数据
const addRowData = () => {
  generateParams.studentInfo.push({
    name: "",
    age: "",
    sex: "",
  });
};
// 删除本行数据
const delRowData = (row) => {
  if (generateParams.studentInfo.length > 1) {
    generateParams.studentInfo.splice(row.index, 1);
  } else {
    ElMessage.warning("最少保留1条数据");
  }
};
// -------------------<<函数执行>>-------------------
onMounted(() => {});
</script>

三、CSS

css 复制代码
<style lang="less" scoped>
.taskInfo {
  width: 100%;
  height: 100%;

  :deep(.taskInfoForm) {
    width: 100%;
    height: calc(100% - 80px);

    .taskInfoSearch {
      width: 100%;
      height: 120px;
      display: flex;
      align-items: center;
      flex-wrap: wrap;

      li {
        width: 25%;
        height: 50%;

        .el-form-item__label {
          color: #fff;
        }

        .el-form-item {
          width: 100%;
          height: 100%;
          margin-bottom: 0px;
          display: flex;
          align-items: center;

          .el-date-editor.el-input,
          .el-input,
          .el-select {
            width: 100% !important;
          }
        }
      }
    }

    .taskInfoAddBtn {
      width: 100%;
      height: 50px;
      display: flex;
      align-items: center;
      justify-content: flex-end;
    }

    .taskInfoTab {
      width: 100%;
      height: calc(100% - 170px);
      position: relative;

      .el-table {
        width: 100%;
        height: 100%;
        background: transparent !important;
        position: absolute;

        .el-form-item {
          width: 100%;
          margin-bottom: 0px;

          .el-form-item__content {
            margin-left: 0px !important;
            display: flex;
            align-items: center;
            justify-content: center;

            .el-input,
            .el-select {
              width: 80% !important;
            }
          }
        }

        td,
        th {
          text-align: center;
        }
      }
    }
  }

  .generate {
    width: 100%;
    height: 80px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>
相关推荐
m0_748247804 分钟前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
ZJ_.31 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
GIS开发特训营36 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood1 小时前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
joan_851 小时前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
还是大剑师兰特2 小时前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
Watermelo6172 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
一个处女座的程序猿O(∩_∩)O4 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
燃先生._.10 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js