Vue3的CRUD模版(附Demo)

目录

  • 前言
  • 模版

前言

用惯Vue2之后,在碰Vue3后,整体还是有所区别

此文主要做一个回顾总结

假设界面如下:

在这里插入图片描述

可CRUD,对应的新增 添加一些必选项:

在这里插入图片描述

其中数据库的设计如下:
在这里插入图片描述

模版

对应需要注意参数位置、初始化表单,重置表单等位置

其首页界面如下:

<template><ContentWrap><!-- 搜索工作栏 --><el-formclass="-mb-15px":model="queryParams"ref="queryFormRef":inline="true"label-width="68px"><el-form-item label="企业名称" prop="enterpriseName"><el-inputv-model="queryParams.enterpriseName"placeholder="请输入企业名称"clearable@keyup.enter="handleQuery"class="!w-240px"/></el-form-item><el-form-item label="信用代码" prop="creditCode"><el-inputv-model="queryParams.creditCode"placeholder="请输入信用代码"clearable@keyup.enter="handleQuery"class="!w-240px"/></el-form-item><el-form-item label="注册人" prop="registrant"><el-inputv-model="queryParams.registrant"placeholder="请输入注册人"clearable@keyup.enter="handleQuery"class="!w-240px"/></el-form-item><el-form-item label="联系电话" prop="contactNumber"><el-inputv-model="queryParams.contactNumber"placeholder="请输入联系电话"clearable@keyup.enter="handleQuery"class="!w-240px"/></el-form-item><el-form-item label="创建时间" prop="createTime"><el-date-pickerv-model="queryParams.createTime"value-format="YYYY-MM-DD HH:mm:ss"type="daterange"start-placeholder="开始日期"end-placeholder="结束日期":default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"class="!w-240px"/></el-form-item><el-form-item label="审批通过与否" prop="status"><el-selectv-model="queryParams.status"placeholder="请选择审批通过与否"clearableclass="!w-240px"><el-optionv-for="dict in getStrDictOptions(DICT_TYPE.DSP_PASS_OR_NOT)":key="dict.value":label="dict.label":value="dict.value"/></el-select></el-form-item><el-form-item><el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button><el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button><el-buttontype="primary"plain@click="openForm('create')"v-hasPermi="['dangerous:enterprise-registry:create']"><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button><el-buttontype="success"plain@click="handleExport":loading="exportLoading"v-hasPermi="['dangerous:enterprise-registry:export']"><Icon icon="ep:download" class="mr-5px" /> 导出</el-button></el-form-item></el-form></ContentWrap><!-- 列表 --><ContentWrap><el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"><el-table-column label="序号" align="center" prop="id" /><el-table-column label="企业名称" align="center" prop="enterpriseName" /><el-table-column label="信用代码" align="center" prop="creditCode" /><el-table-column label="注册人" align="center" prop="registrant" /><el-table-column label="联系电话" align="center" prop="contactNumber" /><el-table-columnlabel="创建时间"align="center"prop="createTime":formatter="dateFormatter"width="180px"/><el-table-column label="审批通过与否" align="center" prop="status"><template #default="scope"><dict-tag :type="DICT_TYPE.DSP_PASS_OR_NOT" :value="scope.row.status" /></template></el-table-column><el-table-column label="操作" align="center"><template #default="scope"><el-buttonlinktype="primary"@click="openForm('update', scope.row.id)"v-hasPermi="['dangerous:enterprise-registry:update']">编辑</el-button><el-buttonlinktype="danger"@click="handleDelete(scope.row.id)"v-hasPermi="['dangerous:enterprise-registry:delete']">删除</el-button></template></el-table-column></el-table><!-- 分页 --><Pagination:total="total"v-model:page="queryParams.pageNo"v-model:limit="queryParams.pageSize"@pagination="getList"/></ContentWrap><!-- 表单弹窗:添加/修改 --><EnterpriseRegistryForm ref="formRef" @success="getList" />
</template><script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { EnterpriseRegistryApi, EnterpriseRegistryVO } from '@/api/dangerous/enterpriseregistry'
import EnterpriseRegistryForm from './EnterpriseRegistryForm.vue'/** 企业信息 列表 */
defineOptions({ name: 'EnterpriseRegistry' })const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化const loading = ref(true) // 列表的加载中
const list = ref<EnterpriseRegistryVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({pageNo: 1,pageSize: 10,enterpriseName: undefined,creditCode: undefined,registrant: undefined,contactNumber: undefined,createTime: [],status: undefined,
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中/** 查询列表 */
const getList = async () => {loading.value = truetry {const data = await EnterpriseRegistryApi.getEnterpriseRegistryPage(queryParams)list.value = data.listtotal.value = data.total} finally {loading.value = false}
}/** 搜索按钮操作 */
const handleQuery = () => {queryParams.pageNo = 1getList()
}/** 重置按钮操作 */
const resetQuery = () => {queryFormRef.value.resetFields()handleQuery()
}/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {formRef.value.open(type, id)
}/** 删除按钮操作 */
const handleDelete = async (id: number) => {try {// 删除的二次确认await message.delConfirm()// 发起删除await EnterpriseRegistryApi.deleteEnterpriseRegistry(id)message.success(t('common.delSuccess'))// 刷新列表await getList()} catch {}
}/** 导出按钮操作 */
const handleExport = async () => {try {// 导出的二次确认await message.exportConfirm()// 发起导出exportLoading.value = trueconst data = await EnterpriseRegistryApi.exportEnterpriseRegistry(queryParams)download.excel(data, '企业信息.xls')} catch {} finally {exportLoading.value = false}
}/** 初始化 **/
onMounted(() => {getList()
})
</script>

其表单内容如下:

<template><Dialog :title="dialogTitle" v-model="dialogVisible"><el-formref="formRef":model="formData":rules="formRules"label-width="100px"v-loading="formLoading"><el-form-item label="企业名称" prop="enterpriseName"><el-input v-model="formData.enterpriseName" placeholder="请输入企业名称" /></el-form-item><el-form-item label="信用代码" prop="creditCode"><el-input v-model="formData.creditCode" placeholder="请输入信用代码" /></el-form-item><el-form-item label="注册人" prop="registrant"><el-input v-model="formData.registrant" placeholder="请输入注册人" /></el-form-item><el-form-item label="联系电话" prop="contactNumber"><el-input v-model="formData.contactNumber" placeholder="请输入联系电话" /></el-form-item><el-form-item label="审批通过与否" prop="status"><el-radio-group v-model="formData.status"><el-radiov-for="dict in getStrDictOptions(DICT_TYPE.DSP_PASS_OR_NOT)":key="dict.value":label="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item></el-form><template #footer><el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button><el-button @click="dialogVisible = false">取 消</el-button></template></Dialog>
</template>
<script setup lang="ts">
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { FormRules } from 'element-plus'
import { EnterpriseRegistryApi, EnterpriseRegistryVO } from '@/api/dangerous/enterpriseregistry'/** 企业信息 表单 */
defineOptions({ name: 'EnterpriseRegistryForm' })const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
const formData = ref({id: undefined,enterpriseName: undefined,creditCode: undefined,registrant: undefined,contactNumber: undefined,status: undefined,
})
const formRules = reactive<FormRules>({enterpriseName: [{ required: true, message: '企业名称不能为空', trigger: 'blur' }],creditCode: [{ required: true, message: '信用代码不能为空', trigger: 'blur' }],registrant: [{ required: true, message: '注册人不能为空', trigger: 'blur' }],contactNumber: [{ required: true, message: '联系电话不能为空', trigger: 'blur' }],status: [{ required: false, message: '联系电话不能为空', trigger: 'blur' }]
})
const formRef = ref() // 表单 Ref/** 打开弹窗 */
const open = async (type: string, id?: number) => {dialogVisible.value = truedialogTitle.value = t('action.' + type)formType.value = typeresetForm()// 修改时,设置数据if (id) {formLoading.value = truetry {formData.value = await EnterpriseRegistryApi.getEnterpriseRegistry(id)} finally {formLoading.value = false}}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {// 校验表单await formRef.value.validate()// 提交请求formLoading.value = truetry {const data = formData.value as unknown as EnterpriseRegistryVOif (formType.value === 'create') {await EnterpriseRegistryApi.createEnterpriseRegistry(data)message.success(t('common.createSuccess'))} else {await EnterpriseRegistryApi.updateEnterpriseRegistry(data)message.success(t('common.updateSuccess'))}dialogVisible.value = false// 发送操作成功的事件emit('success')} finally {formLoading.value = false}
}/** 重置表单 */
const resetForm = () => {formData.value = {id: undefined,enterpriseName: undefined,creditCode: undefined,registrant: undefined,contactNumber: undefined,status: undefined,}formRef.value?.resetFields()
}
</script>

对应后端的接口传输如下:

import request from '@/config/axios'// 企业信息 VO
export interface EnterpriseRegistryVO {id: number // 序号enterpriseName: string // 企业名称creditCode: string // 信用代码registrant: string // 注册人contactNumber: number // 联系电话status: string // 审批通过与否
}// 企业信息 API
export const EnterpriseRegistryApi = {// 查询企业信息分页getEnterpriseRegistryPage: async (params: any) => {return await request.get({ url: `/dangerous/enterprise-registry/page`, params })},// 查询企业信息详情getEnterpriseRegistry: async (id: number) => {return await request.get({ url: `/dangerous/enterprise-registry/get?id=` + id })},// 新增企业信息createEnterpriseRegistry: async (data: EnterpriseRegistryVO) => {return await request.post({ url: `/dangerous/enterprise-registry/create`, data })},// 修改企业信息updateEnterpriseRegistry: async (data: EnterpriseRegistryVO) => {return await request.put({ url: `/dangerous/enterprise-registry/update`, data })},// 删除企业信息deleteEnterpriseRegistry: async (id: number) => {return await request.delete({ url: `/dangerous/enterprise-registry/delete?id=` + id })},// 导出企业信息 ExcelexportEnterpriseRegistry: async (params) => {return await request.download({ url: `/dangerous/enterprise-registry/export-excel`, params })},
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(41)5.6-5.8数据结构(栈和队列的应用和数组)

1.栈在括号匹配中的应用 #define _CRT_SECURE_NO_WARNINGS #define MaxSize 10 typedef struct { char data[MaxSize];//静态数组存放栈中元素 int top; //栈顶指针 }SqStack;//初始化栈 void InitStack(SqStack& S);//判断栈是否为空 bool StackEmpty(SqStack S…

Feign 第一次调用为什么会很慢?

feign调用的大致过程&#xff1f; Feign进行远程调用的&#xff0c;这里面包括&#xff0c;注册中心、负载均衡、FeignClient之间的关系&#xff0c;微服务通过不论是eureka、nacos也好注册到服务端&#xff0c;Feign是靠Ribbon做负载的&#xff0c;而Ribbon需要拿到注册中心的…

从零开始构建现代深度学习框架:数据支持、网站链接与代码步骤

文章目录 一、数据支持二、网站链接三、代码步骤1. 导入必要的库和模块2. 加载和预处理数据&#xff08;以MNIST为例&#xff09;3. 定义模型结构4. 编译模型5. 训练模型6. 评估模型 一、数据支持 在构建深度学习框架的过程中&#xff0c;数据是不可或缺的。以下是一些可能用到…

android进阶-Binder

参考&#xff1a;Android——Binder机制-CSDN博客 机制&#xff1a;Binder是一种进程间通信的机制 驱动&#xff1a;Binder是一个虚拟物理设备驱动 应用层&#xff1a;Binder是一个能发起进程间通信的JAVA类 Binder相对于传统的Socket方式&#xff0c;更加高效Binder数据拷贝…

豆芽机置入语音芯片WTN6040-8S:开启智能生活新篇章,让豆芽制作更便捷有趣

豆芽机的开发背景&#xff1a; 豆芽作为一种营养丰富、味道鲜美的食品&#xff0c;深受广大消费者的喜爱。然而&#xff0c;传统的豆芽生产过程繁琐&#xff0c;需要耗费大量的时间和人力&#xff0c;且存在生产效率低、质量不稳定等问题。随着人们生活节奏的加快和对健康饮食的…

DataLab-数据分析的Ai辅助工具

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;DataLab是一个由DataCamp提供的强大在线数据分析平台&#xff0c;它通过AI技术简化了数据处理流程&#xff0c;使得用户无需编程或数据分析的高级技能即可快速获取数据洞察。它支持多种数据源&#xff0c;包…

C++多态实现原理详解

阅读引言&#xff1a; 我想象了一下&#xff0c; 假如人有突然问我什么是多态&#xff0c; 我该如何给别人说清楚呢&#xff1f;所以写下这篇文章&#xff0c; 希望大家看完有所收获。 ①. 开胃小菜 先看这样一个开胃小菜 这里我有点小小的疑惑&#xff0c; 大小为啥是1。 在C…

Python | Leetcode Python题解之第74题搜索二维矩阵

题目&#xff1a; 题解&#xff1a; class Solution:def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:row,col len(matrix),len(matrix[0])row_l,row_r 0,row-1while row_l < row_r:m (row_lrow_r)//2if target < matrix[m][0]:row_r m-1…

使用 Docker 部署 VS Code in The Browser

1&#xff09;介绍 GitHub&#xff1a;https://github.com/coder/code-server 在日常学习工作中&#xff0c;Vscode 已成为我们首选的代码编辑器。然而&#xff0c;其局限性在于当我们从家到公司移动时&#xff0c;难以保持连续的编码体验。针对这一痛点&#xff0c;虽然市面上…

oracle 数据库与服务、实例与SID、表空间、用户与表模式

一、数据库与数据库服务: 概念:就是一个数据库的标识,在安装时就要想好,以后一般不修改,修改起来也麻烦,因为数据库一旦安装,数据库名就写进了控制文件,数据库表,很多地方都会用到这个数据库名。是数据库系统的入口,它会内置一些高级权限的用户如SYS,SYSTEM等。我们…

11.买卖股票的最佳时机Ⅰ

文章目录 题目简介题目解答解法一&#xff1a;一次遍历代码&#xff1a;复杂度分析&#xff1a; 题目链接 大家好&#xff0c;我是晓星航。今天为大家带来的是 买卖股票的最佳时机面试题Ⅰ 相关的讲解&#xff01;&#x1f600; 题目简介 题目解答 解法一&#xff1a;一次遍历…

怎么把手机ip地址变成了外省

在日常使用中&#xff0c;有时我们可能因为某些原因需要快速切换手机的IP地址&#xff0c;特别是当需要从一个省份切换到另一个省份的IP时。这种需求可能来源于网络访问限制、地理位置相关服务的使用、或者网络安全等方面的考虑。那么&#xff0c;怎么把手机IP地址变成外省呢&a…

Adobe Premiere Pro v24.3.0 解锁版 (领先的视频编辑软件)

前言 Adobe Premiere Pro&#xff08;简称PR&#xff09;是一款知名的专业视频编辑软件&#xff0c;数字视频剪辑软件。主要用来编辑视频和音频&#xff0c;可以在RGB和YUV色彩空间中以高达32位色彩的视频分辨率对4K和更高质量的视频文件进行编辑&#xff0c;支持VST音频插件和…

C++ 搜索二叉树

目录 1.二叉搜索树概念 2. 实现二叉搜索树 2.1. 二叉搜索树的插入 2.2查找 2.3删除节点 3.二叉树的应用&#xff08;KV结构&#xff09; 1.二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为…

Web界面加持!数据库备份神器,助你轻松备份数据!

使用这款带有Web界面的数据库备份神器&#xff0c;你可以轻松设置定时备份&#xff0c;确保数据安全无忧。备份结果即时通知&#xff0c;让你随时掌握备份状态。备份完成后&#xff0c;你将收到备份结果通知。无论是成功备份还是出现错误&#xff0c;你都能及时了解备份情况&am…

自适应熔断限流揭秘

原创 Chasen 拍码场 前言 自适应熔断与限流是在分布式系统中常用的机制&#xff0c;用于保护系统免受服务雪崩效应与突发流量影响。它能够根据系统的负载情况和性能指标自动调整限流策略&#xff0c;以确保系统能提供稳定可靠的服务&#xff0c;目前在业内已经有了不少的探索…

代码无界,创新无限!华为云开发者日 · 广州站来了!

5月23日&#xff0c;2024年首场华为云开发者日HDC.Cloud Day将在广州盛大举行。这场技术派对将为开发者们带来一场无与伦比的技术盛宴。在这里&#xff0c;开发者们将有机会现场聆听行业专家的精彩分享&#xff0c;深度了解众多前沿产品的最新技术和功能&#xff0c;并与行业专…

Sass语法介绍-运算

04 【Sass语法介绍-运算】 1.前言 运算是一种通过已知量可能的组合&#xff0c;获得新的量的行为。Sass 中也为我们提供了各种各样的运算&#xff0c;以便我们更好的处理样式代码。本节我们将学习 Sass 中的数字运算、关系运算、除法运算、颜色运算、字符串运算等等… 2.什么…

OSPF虚链路

原理概述 通常情况下&#xff0c;一个OSPF网络的每个非骨干区域都必须与骨干区域通过ABR路由器直接连接&#xff0c;非骨干区域之间的通信都需要通过骨干区域进行中转。但在现实中&#xff0c;可能会因为各种条件限制&#xff0c;导致非骨干区域和骨干区域无法直接连接&#x…

[muduo网络库]——muduo库三大核心组件之 Poller/EpollPoller类(剖析muduo网络库核心部分、设计思想)

接着上文&#xff0c;[muduo网络库]——muduo库三大核心组件之Channel类&#xff08;剖析muduo网络库核心部分、设计思想&#xff09;&#xff0c;本章我们来学习muduo网络库中第二大核心组件Poller/EpollPoller类。 先回顾一下三大核心组件之间的关系。 接着我们进入正题。 P…