vue3+antd-vue@4 a-form 嵌套a-table 实现行内 勾选才进行检验

一、效果图如下

二、实现方法

以下方法可以判断当前行是否选中(核心实现代码)

javascript 复制代码
// 判断是否是选中的数据
const isSeledted = computed(() => record => {
  return state.selectedRowKeys.some(id => id === record.id);
});

在需要需要检验的字段的判断一下就好, 如果当前行勾选了, 就加上rules的校验, 否则就为rules = null

javascript 复制代码
:rules="isSeledted(record) ? [{ required: true, message: '请输入用途', trigger: 'blur' }] : null"
html 复制代码
<template #bodyCell="{ column, text, record, index }">
  <template v-if="column.dataIndex == 'purpose'">
    <div style="height: 44px" v-if="currentStep === 0">
      <a-form-item
        class="custom-form-item"
        label=" "
        :colon="false"
        :name="[index, 'purpose']"
        :rules="isSeledted(record) ? [{ required: true, message: '请输入用途', trigger: 'blur' }] : null">
        <a-input style="width: 100%" v-model:value="record[column.dataIndex]"></a-input>
      </a-form-item>
    </div>
    <span v-else>{{ text }}</span>
  </template>
  <template v-else-if="column.dataIndex == 'MBstate'">
    <span>已分配</span>
  </template>
</template>

三、完整代码

html 复制代码
<template>
  <div class="allot-warp">
    <a-form ref="tableFormRef" :model="state.tableSource" :label-col="{ style: { width: '10px' } }" :wrapper-col="{ span: 0 }">
        <a-table
          :row-key="_ => _.id"
          class="ant-table-striped"
          bordered
          :dataSource="tableSource"
          :columns="resultTableColumns"
          :pagination="Pagination"
          :scroll="{ x: tableWidth }"
          :row-selection="
            currentStep == 0
              ? {
                  selectedRowKeys: selectedRowKeys,
                  onChange: handleSelectChange
                }
              : null
          "
          :row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)">
          <template #headerCell="{ column }">
            <template v-if="column.dataIndex === 'result'">
              <div class="result-warp">
                <span>配置结果</span>
                <a-button type="link" @click="handleConfigResult">
                  <template #icon>
                    <SearchOutlined />
                  </template>
                </a-button>
              </div>
            </template>
          </template>
          <template #title="{ column }">
            <div v-if="currentStep == 1" style="display: flex; justify-content: space-between; align-items: center">
              <span>!红色背景代表配置校验未通过,黄色背景代表配置校验需要二次确认,绿色背景代表配置校验通过</span>
              <a-button type="primary" size="small" @click="handleExport">
                导出
                <template #icon>
                  <ArrowDownOutlined />
                </template>
              </a-button>
            </div>
          </template>
          <template #bodyCell="{ column, text, record, index }">
            <template v-if="column.dataIndex == 'purpose'">
              <div style="height: 44px" v-if="currentStep === 0">
                <a-form-item
                  class="custom-form-item"
                  label=" "
                  :colon="false"
                  :name="[index, 'purpose']"
                  :rules="isSeledted(record) ? [{ required: true, message: '请输入用途', trigger: 'blur' }] : null">
                  <a-input style="width: 100%" v-model:value="record[column.dataIndex]"></a-input>
                </a-form-item>
              </div>
              <span v-else>{{ text }}</span>
            </template>
            <template v-else-if="column.dataIndex == 'MBstate'">
              <span>已分配</span>
            </template>
          </template>
        </a-table>
      </a-form>
  </div>
</template>

<script setup>
import { ArrowDownOutlined, SearchOutlined } from '@ant-design/icons-vue';
import { Modal } from 'ant-design-vue';
import { computed, h, reactive, ref, watch } from 'vue';
import VLANConfigDetail from '../components/VLANConfigDetail.vue';
const steps = [{ title: '分配选择' }, { title: '配置校验' }, { title: '分配入库' }];
let currentStep = ref(0);
const state = reactive({
  orderInfo: {
    orderId: ''
  },
  selectedRowKeys: []
});

let resultTableColumns = ref();

import useTable from './hooks/useTable.js';
const { tableSource, tableColumns, step2TableColumns, tableWidth, Pagination, getListFn, handleConfigResult, handleExport } = useTable();

const handleSelectChange = (selectedRowKeys, selectedRows) => {
  state.selectedRowKeys = selectedRowKeys;
  console.log('-------- selectedRowKeys --------', state.selectedRowKeys);
};

// 判断是否是选中的数据
const isSeledted = computed(() => record => {
  return state.selectedRowKeys.some(id => id === record.id);
});

// 查询接口
getListFn();

const configDetailRef = ref(null);
// 查看VLAN配置详情
const handleDetail = () => {
  configDetailRef.value.init('allot');
};

// 确认分配
const handleAllotSubmit = () => {
  console.log('handleAllotSubmit');
  Modal.confirm({
    title: '分配选择提交',
    content: '确认提交分配选择吗,确认提交即进行下一步配置校验',
    okText: '确 认',
    cancelText: '取 消',
    centered: true,
    onOk() {
      currentStep.value = 1;
    },
    onCancel() {}
  });
};

let step4Tip = row => {
  return h('div', null, [
    h('div', {}, [h('div', {}, '情景1:'), h('div', {}, `${row.tip}`)]),
    h('div', {}, [h('div', {}, '情景1:'), h('div', {}, `${row.tip}`)]),
    h('div', {}, [h('div', {}, '情景1:'), h('div', {}, `${row.tip}`)])
  ]);
};
// 确认配置检验
const handleAllot2Submit = () => {
  Modal.confirm({
    title: '预埋确认',
    content: step4Tip({ tip: '经再次校验,xx平面目标VLAN值:xxx,xxx现网未配置,无法预埋!请进行实施配置' }),
    okText: '确 认',
    cancelText: '取 消',
    centered: true,
    onOk() {
      currentStep.value = 2;
    },
    onCancel() {
      console.log('Cancel');
    }
  });
};

// 返回上一步
const handleBack = () => {};

watch(
  currentStep,
  val => {
    if (val === 1) {
      resultTableColumns.value = step2TableColumns.value;
    } else {
      resultTableColumns.value = tableColumns.value;
    }
  },
  { immediate: true }
);
</script>

<style lang="less" scoped>
.allot-warp {
  width: 100%;
  height: 100%;
  padding: 20px;
  background-color: #f5f5f5;
  .setps-warp {
    width: 100%;
    padding: 50px 40px;
    background-color: #fff;
  }
  .content-warp {
    margin-top: 15px;
    padding: 40px 20px;
    background-color: #fff;
    .content-tip {
      padding: 0 0 20px 0;
      .tip-title {
        font-size: 16px;
      }
      .tip-warp {
        margin-top: 10px;
        padding-left: 20px;
        .tip-item {
          margin-bottom: 10px;
          font-size: 14px;
        }
      }
    }
  }
}
.order-info-warp {
  padding: 20px 20px 0 20px;
  background-color: #fff;
  display: flex;
  .order-title {
    font-size: 18px;
    font-weight: 600;
    display: flex;
    align-items: center;
    margin-bottom: 20px;
  }
  .order-title::before {
    content: '';
    display: inline-block;
    width: 5px;
    height: 18px;
    background-color: #1890ff;
    margin-right: 10px;
  }
  .order-item-warp {
    margin: 10px 0;
    label {
      display: inline-block;
      width: 100px;
      padding-left: 20px;
    }
  }
}
</style>
相关推荐
栈老师不回家2 分钟前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙8 分钟前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
一颗松鼠12 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds32 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
程序媛小果1 小时前
基于java+SpringBoot+Vue的宠物咖啡馆平台设计与实现
java·vue.js·spring boot
小光学长1 小时前
基于vue框架的的流浪宠物救助系统25128(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
数据库·vue.js·宠物
阿伟来咯~1 小时前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端1 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱1 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai2 小时前
uniapp
前端·javascript·vue.js·uni-app