arco-design 自定义table和for循环自定义form-item并添加自定义校验

代码

<template>
  <div class="list-container">
    <Breadcrumb
      :items="['menu.generateRecords', 'menu.generateRecordsDetail']"
      :needBack="true"
    />
    <a-card class="general-card">
      <PageQuery
        ref="pageQuery"
        :show-add="true"
        :provider-list="state.providerList"
        :telecom-status-list="state.telecomStatusList"
        :telecom-list="state.telecomList"
        :sim-status-list="state.simStatusList"
        @fetch-list-query="fetchListQuery"
        @fetch-list-reset="fetchListReset"
        @add-data="addData"
        @upload="handleUpload"
        @import="handleImport"
      ></PageQuery>
    </a-card>
    <a-card class="general-card" style="margin-top: 20px">
      <a-table
        :loading="state.tableLoading"
        :columns="state.columnsList"
        :data="state.tableData"
        :pagination="state.basePagination"
        :bordered="{ cell: true }"
        @page-change="onPageChange($event)"
        @page-size-change="onPageSizeChange($event)"
      >
        <template #imei="{ rowIndex, record }">
          <a-input
            v-model="state.tableData[rowIndex].imei"
            @blur="imeiBlur(record)"
          />
        </template>
        <template #iotCardNo="{ rowIndex, record }">
          <a-input
            v-model="state.tableData[rowIndex].iotCardNo"
            @blur="iotCardBlur(record)"
          />
        </template>
        <template
          v-for="(TabItem, index) in state.addColumnsList"
          v-slot:[TabItem.slotName]="{ rowIndex, record }"
          :key="index"
        >
          <a-input
            v-model="state.tableData[rowIndex][TabItem.slotName]"
            @blur="otherBlur(record, TabItem.slotName)"
          />
        </template>
        <template #optional="{ record }">
          <a-button type="text" @click="handleClickDetail(record)">
            详情
          </a-button>
          <a-button type="text" @click="handleClickDetail(record)">
            导出
          </a-button>
        </template>
      </a-table>
    </a-card>
    <!-- 详情组件 -->
    <DetailModal
      ref="DetailModalRef"
      :current-detail="state.currentDetail"
    ></DetailModal>
    <!-- 新增弹窗 -->
    <a-modal
      v-model:visible="insertVisible"
      :footer="false"
      @cancel="closeAddModal"
    >
      <template #title>
        <div class="modal-title">新增桩码</div>
      </template>
      <a-form
        ref="formRef"
        :model="state.form"
        :style="{ width: '100%' }"
        auto-label-width
        @submit="handleAddSubmit"
      >
        <a-form-item
          v-for="(labelItem, indexs) in state.form.formList"
          :key="indexs"
          :field="labelItem.dataIndex"
          :label="labelItem.title"
          :rules="[
            {
              required: true,
              message: `${labelItem.title}不能为空`,
            },
            {
              validator:
                labelItem.dataIndex === 'iotCardNo' ? customValidator : '',
            },
          ]"
          :validate-trigger="['blur', 'change']"
        >
          <a-input
            v-model="state.form[labelItem.dataIndex]"
            :disabled="labelItem.dataIndex === 'orderNo'"
            :placeholder="`请输入${labelItem.title}`"
          />
        </a-form-item>
        <a-form-item>
          <a-space>
            <a-button @click="closeAddModal">取 消</a-button>
            <a-button type="primary" html-type="submit">确 定</a-button>
          </a-space>
        </a-form-item>
      </a-form>
    </a-modal>
    <!-- 导入 -->
    <input
      ref="fileInput"
      type="file"
      style="display: none"
      accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      @change="handleFileChange"
    />
  </div>
</template>

<script lang="ts" setup>
  // @ts-nocheck
  import { ref, reactive, onMounted, getCurrentInstance } from 'vue';
  import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
  import { Message } from '@arco-design/web-vue';
  import {
    generateEquipmentEncodeQuery,
    updateEquipmentEncodeRecordDetailBySortNum,
    addEquipmentEncodeRecordDetail,
    template,
    importImei,
  } from '@/api/purchasing';
  import { useRouter } from 'vue-router';
  import AddModal from '@/views/iotcard/all-card/components/add-modal.vue';
  import PageQuery from './components/PageQuery.vue';
  import DetailModal from './components/detail-modal.vue';
  import { pagination, columnsList } from './config';

  const proxy = getCurrentInstance()?.proxy as any;
  const { currentRoute } = useRouter();
  const route = currentRoute.value;
  const DetailModalRef = ref();
  const fileInput = ref(); // 导入
  const insertVisible = ref(false);
  const state = reactive({
    formQuery: {},
    tableLoading: false,
    tableData: [],
    currentDetail: {},
    basePagination: {
      ...pagination,
    },

    telecomList: [], // 运营商字典
    providerList: [], // 供应商字典
    telecomStatusList: [], // 卡状态(运营商)
    simStatusList: [], // 管理状态
    isFirst: true,
    columnsList: [],
    imei: 'imei',
    addColumnsList: [],
    form: {
      formList: [],
    },
  });
  const fetchData = async (
    params = {
      accessType: 'Web',
      data: {
        ...state.formQuery,
        encodeRecordId: route.query.encodeRecordId,
      },
      page: {
        pageIndex: state.basePagination.current,
        pageSize: state.basePagination.pageSize,
      },
    }
  ) => {
    state.tableLoading = true;
    try {
      const resData = await generateEquipmentEncodeQuery(params);
      state.columnsList = resData.data.ruleNames.map((item) => {
        return {
          title: item.ruleName,
          dataIndex: item.ruleCode,
          slotName: item.ruleCode,
        };
      });
      state.addColumnsList = resData.data.ruleNames.map((item) => {
        return {
          title: item.ruleName,
          dataIndex: item.ruleCode,
          slotName: item.ruleCode,
        };
      });
      state.columnsList.unshift(
        { title: '订单号', dataIndex: 'orderNo' },
        {
          title: 'imei',
          dataIndex: 'imei',
          slotName: 'imei',
        },
        {
          title: '物联网卡编号',
          dataIndex: 'iotCardNo',
          slotName: 'iotCardNo',
        }
      );
      // 表单item数组
      state.form.formList = [];
      state.columnsList.forEach((item) => {
        state.form.formList.push(item);
      });
      // 表单对象
      state.columnsList.forEach((item) => {
        if (item.dataIndex === 'orderNo') {
          state.form[item.dataIndex] = route.query.orderNo;
        } else {
          state.form[item.dataIndex] = '';
        }
      });
      console.log(state.form);
      state.tableData = resData.data.ruleCodes;
      state.basePagination.current = params.page.pageIndex;
      state.basePagination.total = resData.page.total;
    } catch (err) {
      // you can report use errorHandler or other
    } finally {
      state.tableLoading = false;
      state.isFirst = false;
    }
  };
  // imei修改
  // eslint-disable-next-line consistent-return
  const imeiBlur = async (e) => {
    console.log('保存了imei号');
    console.log(e);
    if (e.imei === '' || e.imei === null) {
      return false;
    }
    e.recordId = route.query.encodeRecordId;
    const params = {
      accessType: 'Web',
      data: {
        sortNum: e.sortNum,
        recordId: e.recordId,
        imei: e.imei,
      },
    };
    try {
      const res = await updateEquipmentEncodeRecordDetailBySortNum(params);
      proxy.$message.success('imei修改成功');
    } catch (err) {
      // you can report use errorHandler or other
      console.log(err);
      console.log('请求失败');
    } finally {
      state.tableLoading = false;
    }
  };

  // 物联网卡号修改
  // eslint-disable-next-line consistent-return
  const iotCardBlur = async (e) => {
    console.log('保存了物联网卡号');
    console.log(e);
    if (e.iotCardNo === '' || e.iotCardNo === null) {
      return false;
    }
    const flag: boolean = /^\d{13}$/.test(e.iotCardNo);
    if (!flag) {
      proxy.$message.error('请输入13位纯数字物联卡号');
      return false;
    }

    e.recordId = route.query.encodeRecordId;
    const params = {
      accessType: 'Web',
      data: {
        sortNum: e.sortNum,
        recordId: e.recordId,
        iotCardNo: e.iotCardNo,
      },
    };

    try {
      const res = await updateEquipmentEncodeRecordDetailBySortNum(params);
      proxy.$message.success('物联网卡编号修改成功');
    } catch (err) {
      // you can report use errorHandler or other
      console.log(err);
      console.log('请求失败');
    } finally {
      state.tableLoading = false;
    }
  };
  // 其他字段修改
  // eslint-disable-next-line consistent-return
  const otherBlur = async (e, className) => {
    console.log('修改了其他字段');
    console.log(e);
    console.log(className);
    const key = className;
    console.log(e[className]);

    e.recordId = route.query.encodeRecordId;
    const datas = {
      sortNum: e.sortNum,
      recordId: e.recordId,
      productCode: e[className],
      ruleCode: className,
    };
    const params = {
      accessType: 'Web',
      data: datas,
    };

    try {
      const res = await updateEquipmentEncodeRecordDetailBySortNum(params);
      proxy.$message.success('物联网卡编号修改成功');
    } catch (err) {
      // you can report use errorHandler or other
      console.log(err);
      console.log('请求失败');
    } finally {
      state.tableLoading = false;
    }
  };
  // 新增数据
  const addData = () => {
    console.log('点击了增加');
    console.log(state.form);
    insertVisible.value = true;
  };
  // 取消新增
  const closeAddModal = () => {
    insertVisible.value = false;
    state.form.formList.forEach((item) => {
      item.value = '';
    });
    proxy.$refs.formRef.resetFields();
  };
  // 新增
  const handleAddSubmit = async ({ errors, values }) => {
    if (errors !== undefined) {
      return;
    }

    const list = [];
    console.log(state.form);
    console.log(state.addColumnsList);
    state.addColumnsList.forEach((item) => {
      const obj = {
        imei: state.form.imei,
        iotCardNo: state.form.iotCardNo,
        productCode: '', // value
        recordId: route.query.encodeRecordId,
        ruleCode: '', // key
      };
      obj.ruleCode = item.dataIndex;
      obj.productCode = state.form[item.dataIndex];
      list.push(obj);
    });
    console.log(list);
    const params = {
      accessType: 'Web',
      data: list,
    };
    console.log(params);

    try {
      const resData = await addEquipmentEncodeRecordDetail(params);
      console.log('resData', resData);
      if (resData.code === '0000') {
        Message.success('新增成功');
        closeAddModal();
      }
      fetchData();
    } catch (err) {
      // you can report use errorHandler or other
    } finally {
      state.tableLoading = false;
    }
  };
  // 物联网卡号校验
  const customValidator = (value, callback) => {
    // Your custom validation logic here
    const isValid = /^\d{13}$/.test(value);

    // Call the callback with an error message if validation fails
    if (!isValid) {
      callback('请输入13位纯数字物联卡号');
    } else {
      // Call the callback with no error if validation passes
      callback();
    }
  };

  // 查询
  const fetchListQuery = (e: any) => {
    state.formQuery = e;
    state.basePagination.current = 1;
    fetchData();
  };
  // 重置
  const fetchListReset = (e: any) => {
    state.formQuery = e;
    state.basePagination.current = 1;
    fetchData();
  };
  // 下载
  const handleClickDownload = async () => {
    state.tableLoading = true;
    try {
      const params = {
        accessType: 'Web',
        data: {
          ...state.formQuery,
          pageIndex: state.basePagination.current,
          pageSize: state.basePagination.pageSize,
        },
      };
      const res: any = await exportInstallCard(params);
      if (res.code === '0000') {
        proxy.$message.success('下载成功,请点击传输管理按钮查看下载记录!');
      }
    } catch (err) {
      // you can report use errorHandler or other
    } finally {
      state.tableLoading = false;
    }
  };
  // 模板下载
  const handleUpload = async () => {
    console.log('模板下载');
    state.tableLoading = true;
    try {
      const params = {
        accessType: 'Web',
        data: {},
      };
      const res: any = await template(params);
      const elink = document.createElement('a');
      const blob = new Blob([res], { type: 'application/vnd.ms-excel' });
      elink.style.display = 'none';
      elink.download = `生成记录下载文件.xlsx`;
      elink.href = window.URL.createObjectURL(blob);
      document.body.appendChild(elink);
      elink.click();
      document.body.removeChild(elink);
      proxy.$message.success('下载成功!');
    } catch (err) {
      // you can report use errorHandler or other
    } finally {
      state.tableLoading = false;
    }
  };
  // 导入
  const handleImport = () => {
    console.log('导入');
    fileInput.value.click();
  };
  // 批量导入 - 文件上传
  const handleFileChange = async (event: any) => {
    const file = event.target.files[0];
    if (!file) {
      return;
    }
    if (file.name.split('.')[1] !== 'xlsx') {
      proxy.$message.error('请上传格式为 .xlsx 的文件');
      // 上传完成后重置input
      fileInput.value = document.createElement('input');
      fileInput.value.type = 'file';
      fileInput.value.accept =
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
      fileInput.value.onchange = handleFileChange;
      return;
    }
    const fd = new FormData();
    fd.append('file', file);
    fd.append('recordId', route.query.encodeRecordId);
    const res: any = await importImei(fd);
    // 上传完成后重置input
    fileInput.value = document.createElement('input');
    fileInput.value.type = 'file';
    fileInput.value.accept =
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    fileInput.value.onchange = handleFileChange;

    if (res.code === '0000') {
      proxy.$message.success('导入成功');
    }
  };

  // 页码切换
  const onPageChange = (current: number) => {
    state.basePagination.current = current;
    fetchData();
  };
  // 条数切换
  const onPageSizeChange = (pageSize: number) => {
    state.basePagination.pageSize = pageSize;
    fetchData();
  };
  // 详情
  const handleClickDetail = async (e: any) => {
    state.tableLoading = true;
    try {
      const params = {
        accessType: 'Web',
        data: {
          msisdn: e.msisdn,
          deviceNo: e.deviceNo,
        },
      };
      const res: any = await getInstallCardDetail(params);
      state.currentDetail = res.data || {};
      DetailModalRef.value.showModel(true, e.msisdn);
    } catch (err) {
      // you can report use errorHandler or other
    } finally {
      state.tableLoading = false;
    }
  };

  // 获取字典
  const fetchDict = async () => {
    try {
      const telecomRes: any = await getDict('telecom'); // 运营商
      state.telecomList = telecomRes.data || [];

      const providerRes: any = await getDict('provider'); // 供应商
      state.providerList = providerRes.data || [];

      const telecomStatusRes: any = await getDict('telecom_status'); // 卡状态(运营商状态)
      state.telecomStatusList = telecomStatusRes.data || [];

      const simStatusRes: any = await getDict('sim_status'); // 卡状态(sim卡状态)
      state.simStatusList = simStatusRes.data || [];
    } catch (err) {
      // you can report use errorHandler or other
    }
  };

  const pageQuery = ref(null);

  // 页面初始化信息
  onMounted(() => {
    fetchData();
    // fetchListQuery(pageQuery.value.formQuery);
    // fetchDict();
  });
</script>

<script lang="ts">
  export default {
    name: 'Recording',
  };
</script>

<style lang="less" scoped>
  .btn {
    text-align: center;
    color: white;
    line-height: 24px;
    width: 68px;
    border-radius: 4px;
    margin: auto;
  }
</style>


展示效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

后台返回的数据
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/903726.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DriftingBlues: 1渗透测试

靶机&#xff1a;DriftingBlues: 1 DriftingBlues: 1 ~ VulnHubhttps://www.vulnhub.com/entry/driftingblues-1,625/ 攻击机&#xff1a;kail linux 2024 1,将两台虚拟机网络连接都改为NAT模式&#xff0c;并查看靶机的MAC地址 2&#xff0c;攻击机上做主机扫描发现靶机 靶机I…

一个简单的图像分类项目(四)编写脚本:图像加载器

创建训练和测试的数据集&#xff0c;并创建加载器。lib.load_imags.py: import glob from torch.utils.data import DataLoader, Dataset from torchvision import transformsfrom script.setting import *# 图片处理函数 def img_loader(path):try:img Image.open(path)img …

NLTK无法下载?

以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 nltk无法下载怎么办&#xff1f;什么是NLTK&#xff1f;为什么要用NLTK&#xff1f;如何下载&#xff1f; nltk无法下载怎么办&#xff1f; 什么是NLTK&#xff1f; NLTK是学习自然…

厨艺爱好者的在线互动平台:Spring Boot实现

摘 要 使用旧方法对厨艺交流信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在厨艺交流信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的厨艺交流平台功能…

解决SpringBoot项目启动错误:找不到或无法加载主类

如何解决SpringBoot项目的“找不到或无法加载主类”启动错误 在开发SpringBoot应用时&#xff0c;经常可能会遇到一个启动错误&#xff1a;“错误&#xff1a;找不到或无法加载主类 com.example.controller.demo.DemoApplication”。本文将介绍三种解决这一问题的方法。 方法…

Tessy学习笔记-CTE如何生成测试用例

1&#xff1a;前提工作 在开始设置测试用例之前&#xff0c;我们还需要将树图补充完整&#xff0c;如下图 补充步骤&#xff0c; 1&#xff1a;在palette中&#xff0c;选择两个class拖动到return图标下&#xff0c;然后回到palette中选择DefineParent将class与Return图标连接…

在Java中,需要每120分钟刷新一次的`assetoken`,并且你想使用Redis作为缓存来存储和管理这个令牌

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

《Python游戏编程入门》注-第4章1

《Python游戏编程入门》的第4章是“用户输入&#xff1a;Bomb Cathcer游戏”&#xff0c;通过轮询键盘和鼠标设备状态实现Bomb Cathcer游戏。 1 Bomb Cathcer游戏介绍 “4.1 认识Bomb Cathcer游戏”内容介绍了Bomb Cathcer游戏的玩法&#xff0c;即通过鼠标来控制红色“挡板”…

【HarmonyOS】判断应用是否已安装

【HarmonyOS】判断应用是否已安装 前言 在鸿蒙中判断应用是否已安全&#xff0c;只是通过包名是无法判断应用安装与否。在鸿蒙里新增了一种判断应用安装的工具方法&#xff0c;即&#xff1a;canOpenLink。 使用该工具函数的前提是&#xff0c;本应用配置了查询标签querySch…

【Java基础】2、Java基础语法

f2/fnf2&#xff1a;选中点中的文件名 ​​​​​​​ 1.注释 为什么要有注释&#xff1f; 给别人和以后的自己可以看懂的解释 注释含义 注释是在程序指定位置的说明性信息&#xff1b;简单理解&#xff0c;就是对代码的一种解释 注释分类 单行注释 //注释信息 多行注释…

【Linux系统编程】线程深入运用

目录 一&#xff0c;C线程与系统线程 二&#xff0c;分离线程 三&#xff0c;线程结构 四&#xff0c;__thread关键字 五&#xff0c;Linux线程互斥 1&#xff0c;线程互斥相关的背景概念 2&#xff0c;互斥锁 3&#xff0c;死锁 4&#xff0c;互斥锁的弊端 六&#…

【ACM出版,EI稳定检索,九大高校联合举办, IEEE Fellow支持】2024年计算机视觉与艺术研讨会(CVA 2024)

在线投稿&#xff1a;学术会议-学术交流征稿-学术会议在线-艾思科蓝 2024年计算机视觉与艺术国际学术会议&#xff08;CVA 2024&#xff09;作为2024年人工智能、数字媒体技术与交互设计国际学术会议&#xff08;ICADI 2024)的分会。此次大会旨在汇聚全球在计算机视觉与艺术…

红队工具---Behinder学习

1.什么是Behinder&#xff1f; Behinder 是一款用于网络渗透测试的安全工具&#xff0c;主要用于对 Web 应用进行攻击和漏洞利用。它提供了强大的功能&#xff0c;是一款红队的大杀器&#xff0c;几乎是现代web安全必须学习的一款webshell管理工具。 主要用途 渗透测试&#…

怿星科技薛春宇丨智能汽车软件研发工具链国产化的挑战和探索

2024年7月25日&#xff0c;由上海良益企业管理咨询有限公司主办的“2024域控制器技术论坛“在上海成功举办&#xff0c;十位嘉宾做了精彩分享。“整零有道”将陆续刊出部分演讲的文字实录&#xff0c;以飨读者。 本期刊出怿星科技副总经理薛春宇的演讲实录&#xff1a;智能汽车…

python这10个接口自动化的装饰器

在Python接口自动化测试中&#xff0c;装饰器可以用于增强测试函数的功能或改变其行为。以下是一些可能使用的装饰器示例&#xff1a; 设置和清理环境 setup&#xff1a;用于在测试开始前初始化环境或配置。 class CustomTestRunner: def __init__(self): self.setup_done …

【Spring】Cookie与Session

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;计算机网络那些事 一、Cookie是什么&#xff1f; Cookie的存在主要是为了解决HTTP协议的无状态性问题&#xff0c;即协议本身无法记住用户之前的操作。 "⽆状态" 的含义指的是: 默认情况…

摄像头点击器常见问题——摄像头视窗打开慢

【嵌入式开发】可编程4k蓝牙摄像头点击器_能编程的摄像头-CSDN博客 拥有上述文章产品的朋友出现标题所述问题&#xff0c;可继续往下阅读 出现以上问题&#xff0c;摄像头画面打开较慢&#xff0c;可以按以下操作进行设置 在环境变量里设置一下这个参数&#xff0c;值设置为1&…

Springboot项目搭建的问题

1.第一次出现这个问题是在使用postgresql进行搭建项目的时候&#xff0c;但是配置文件中的驱动一致导入不了 最后发现是meaven中依赖导入不进来&#xff08;不知道为什么&#xff09;&#xff0c;于是手动的在meaven中央仓库下载了对应的jar进行配置 然后项目可以正常启动 2.…

Java-I/O框架06:常见字符编码、字符流抽象类

视频链接&#xff1a;16.16 字符流抽象类_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Tz4y1X7H7?spm_id_from333.788.videopod.episodes&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5&p16 1.常见字符编码 IOS-8859-1收录了除ASCII外&#xff0c;还包括西欧…

搜索引擎算法更新对网站优化的影响与应对策略

内容概要 随着互联网的不断发展&#xff0c;搜索引擎算法也在不断地进行更新和优化。了解这些算法更新的背景与意义&#xff0c;对于网站管理者和优化人员而言&#xff0c;具有重要的指导意义。不仅因为算法更新可能影响到网站的排名&#xff0c;还因为这些变化也可能为网站带…