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>
相关推荐
ZC跨境爬虫7 分钟前
跟着 MDN 学JavaScript day_10:数组——数据的有序集合
android·java·开发语言·前端·javascript
晓131315 分钟前
【Cocos Creator 2.x】篇——第五章 游戏常用关键技术
前端·javascript·vue.js·游戏引擎
W_LuYi18543 分钟前
Tauri + Rust + Vue 3 打造极速轻量桌面应用
java·开发语言·vue.js·rust
qq4356947011 小时前
Vue03
javascript·vue.js
樱花的浪漫1 小时前
Typescript、Zod基础
前端·javascript·人工智能·语言模型·自然语言处理·typescript
用户549591657501 小时前
TinyVue Tree树形控件完全指南
vue.js
竹林8181 小时前
监听智能合约事件,我用 wagmi v2 踩了三天坑,终于找到了稳定方案
前端·javascript
用户852495071841 小时前
Bun 到底是什么?一个比 Node.js "更快更香"的 JS 运行时
javascript·程序员
Momo__1 小时前
SSR 懒水合四件套 — 99%的人不知道 Vue 3.5 藏了这些水合策略
前端·vue.js·性能优化
riuphan1 小时前
JavaScript 事件循环:单线程异步编程的核心机制
前端·javascript