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 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
一 乐3 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
昨天;明天。今天。3 小时前
案例-表白墙简单实现
前端·javascript·css
数云界3 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd3 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常3 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer3 小时前
Vite:为什么选 Vite
前端
小御姐@stella3 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing3 小时前
【React】增量传输与渲染
前端·javascript·面试
GISer_Jing3 小时前
WebGL在低配置电脑的应用
javascript