一套后台管理系统的入门级的增删改查(vue3组合式api+elemment-plus)

news2024/11/17 10:01:48

一、页面示意:

图一

图二

二、组件结构

  • 列表组件 :index.vue,对应图一
  • 添加组件:add.vue,对应图二,用抽屉效果
  • 编辑组件:edit.vue,和添加组件的效果一个。

三、代码

1、列表组件: index.vue

<template>
    <h1>增删改查案例</h1>
    <div>
        <!--查询条件  -->
        <el-form :model="searchData" label-width="40px" :inline="true">
            <el-form-item label="书号">
                <el-input v-model="searchData.id" />
            </el-form-item>
            <el-form-item label="书名">
                <el-input v-model="searchData.name" />
            </el-form-item>
            <el-form-item label="作者">
                <el-input v-model="searchData.author" />
            </el-form-item>
            <el-form-item label="价格">
                <el-input v-model="searchData.minprice" />
            </el-form-item>
            <el-form-item label="-->">
                <el-input v-model="searchData.maxprice" />
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="searchFn">查询</el-button>
                <el-button @click="showAdd">添加</el-button>
            </el-form-item>
        </el-form>
    </div>
    <div>
        <!-- 书籍列表 -->
        <el-table :data="bookData" stripe style="width: 100%">
            <el-table-column prop="id" label="书号" width="180" />
            <el-table-column prop="name" label="书名" width="180" />
            <el-table-column prop="author" label="作者" />
            <el-table-column prop="price" label="价格" />
            <el-table-column  label="类型" >
                <template #default="scope">
                    <span>{{typeObj[scope.row.type]}}</span>
                </template>
            </el-table-column>
            <el-table-column label="图片">
                <template #default="scope">
                    <img :src="scope.row.img" style="width: 100px;height: 100px" />
                </template>
            </el-table-column>

            <el-table-column fixed="right" label="操作" width="120">
                <template #default="scope">
                    <el-button link type="primary" size="small" @click="showEdit(scope.row.id)">
                        编辑
                    </el-button>
                    <el-button link type="primary" size="small" @click.prevent="deleteBook(scope.row.id)">
                        删除
                    </el-button>
                </template>
            </el-table-column>
        </el-table>
        <el-drawer v-model="drawer" title="添加书籍" direction="rtl" :before-close="handleClose">
            <AddBook @close="closeFn" @ok="okFn"></AddBook>
        </el-drawer>
        <el-drawer v-model="drawerEdit" title="修改书籍" direction="rtl" >
            <EditBook :id="editId" @ok="editOkFn" @close="editCloseFn" ></EditBook>
        </el-drawer>
    </div>
</template>

<script  setup>
import { reactive, onMounted,ref } from "vue";
import { getBooksApi, getBooksByCondationApi, deleteBookApi } from "@/api/crud";
import AddBook from "./Add.vue";
import EditBook from "./edit.vue";


const typeObj = {
    "new":"最新",
    "hot":"热卖"
}


// 书籍数据
let bookData = reactive([]);

//一、 获取书籍信息
const getBooks = () => {
    getBooksApi()
        .then(res => {
            if (res.data) {
                console.log("bookData前", bookData);
                // bookData = res.data;
                bookData.length = 0;
                bookData.push(...res.data);
                console.log("bookData后", bookData);
            }
        })
        .catch(err => {
            console.log("获取数据出错", err);
        })
}
onMounted(() => {
    getBooks();
})

// 二、查询书籍
const searchData = reactive({
    "id": "",
    "name": "",
    "author": "",
    "minprice": "",
    "maxprice": ""
})

const searchFn = () => {

    const temp = {};
    for (const key in searchData) {
        if (searchData[key] !== "") {
            temp[key] = searchData[key];
        }
    }

    if (temp["minprice"]) {
        delete temp["minprice"];
        temp["price_gte"] = searchData.minprice;
    }

    if (temp["maxprice"]) {
        delete temp["maxprice"];
        temp["price_lte"] = searchData.maxprice;
    }


    getBooksByCondationApi(temp)
        .then(res => {
            if (res.data) {
                bookData.length = 0;
                bookData.push(...res.data);
            }
        })
}


// 三、删除书籍
const deleteBook = (id) => {

    deleteBookApi(id)
        .then(res => {
            console.log("删除的返回res", res);
            // 删除成功后,重新获取数据
            getBooks();
        })
}


// 四、添加
const drawer = ref(false)

const handleClose = (done) => {
  ElMessageBox.confirm('Are you sure you want to close this?')
    .then(() => {
      done()
    })
    .catch(() => {
      // catch error
    })
}

// 显示添加页面
const showAdd=()=>{
    drawer.value=true;
}

const closeFn=()=>{
    drawer.value = false;
}

const okFn=()=>{
    closeFn();
    getBooks();
}

// 五、修改
const drawerEdit = ref(false);
const editId = ref("");//修改的书籍的id

// 显示修改页面
const showEdit=(id)=>{
    editId.value=id;
    drawerEdit.value=true;
}

const editCloseFn=()=>{
    editId.value ="";
    drawerEdit.value = false;
}

const editOkFn=()=>{
    editCloseFn();
    getBooks();
}


</script>


<style lang="css" scoped></style>

2、添加组件:add.vue

<template>
    <el-form ref="formRef" :model="newBook" label-width="120px" :rules="rules">
        <el-form-item label="书号" prop="id">
            <el-input v-model="newBook.id" />
        </el-form-item>
        <el-form-item label="书名" prop="name">
            <el-input v-model="newBook.name" />
        </el-form-item>
        <el-form-item label="作者" prop="author">
            <el-input v-model="newBook.author" />
        </el-form-item>
        <el-form-item label="价格" prop="price">
            <el-input v-model="newBook.price" />
        </el-form-item>
        <el-form-item label="图片" prop="img">
            <el-input v-model="newBook.img" />
        </el-form-item>
        <el-form-item label="类型" prop="type">
            <!-- <el-input v-model="newBook.type" /> -->
            <el-select v-model="newBook.type" class="m-2" placeholder="请选择书籍类型" size="large">
                <!-- <el-option v-for="item in booktypes" :key="item.id" :label="item.name" :value="item.value" /> -->
                <el-option label="最新" value="new" />
                <el-option label="热卖" value="hot" />
            </el-select>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="addBookFn(formRef)">添加</el-button>
            <el-button @click="cancelFn">取消</el-button>
        </el-form-item>
    </el-form>
</template>
    
<script  setup>
import { reactive, ref } from 'vue';
import { addBookApi,getBookTypeApi } from "@/api/crud"

const emit = defineEmits(['close', "ok"]);

const booktypes = reactive([]);

const getBookType = () => {
    getBookTypeApi()
    .then(res=>{
        if(res.data){
            booktypes.length=0;
            booktypes.push(...res.data);
        }
    })
}

getBookType();

const formRef = ref();
//  定义添加的书籍
const newBook = reactive({
    "id": "",
    "name": "",
    "author": "",
    "price": 0,
    "img": "",
    "type": ""
})



// 表单验证的规则
const rules = reactive({
    "id": [
        { required: true, message: '请输入书号', trigger: 'blur' }
    ],
    "name": [
        { required: true, message: '请输入书名', trigger: 'blur' }
    ],
    "author": [
        { required: true, message: '请输入作者', trigger: 'blur' }
    ],
    "price": [
        { required: true, message: '请输入价格', trigger: 'blur' }
    ],
    "img": [
        { required: true, message: '请输入图片地址', trigger: 'blur' }
    ],
    "type": [
        { required: true, message: '请输入类型', trigger: 'blur' }
    ],
})


const addBookFn = (formEl) => {
    if (!formEl) {
        return;
    }
    console.log("newBook",newBook);

    formEl.validate((isOk) => {
        if (isOk) {
            addBookApi(newBook)
                .then(res => {
                    console.log(res);
                    if (res.data) {
                        // 添加成功
                        alert("添加成功!");
                        // 关闭弹窗
                        emit("ok");
                    }
                })
                .catch(err => {

                })
        }
    })


}

const cancelFn = () => {
    emit('close');
}



</script>

3、编辑组件:edit.vue

<template>
    <el-form ref="formRef" :model="editBook" label-width="120px" :rules="rules">
        <el-form-item label="书号" prop="id">
            <el-input v-model="editBook.id" />
        </el-form-item>
        <el-form-item label="书名" prop="name">
            <el-input v-model="editBook.name" />
        </el-form-item>
        <el-form-item label="作者" prop="author">
            <el-input v-model="editBook.author" />
        </el-form-item>
        <el-form-item label="价格" prop="price">
            <el-input v-model="editBook.price" />
        </el-form-item>
        <el-form-item label="图片" prop="img">
            <el-input v-model="editBook.img" />
        </el-form-item>
        <el-form-item label="类型" prop="type">
            <el-input v-model="editBook.type" />
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="editBookFn(formRef)">修改</el-button>
            <el-button @click="cancelFn">取消</el-button>
        </el-form-item>
    </el-form>
</template>
    
<script  setup>
import { reactive, ref,watch } from 'vue';
import { getBookDetailApi,editBookApi } from '@/api/crud';

const props = defineProps(["id"]);

const formRef = ref();

//  定义修改的书籍
const editBook = reactive({
    "id": "",
    "name": "",
    "author": "",
    "price": 0,
    "img": "",
    "type": ""
})


// 获取当前修改的书籍信息
const getBookDetail = async () => {
    try {
        const res = await getBookDetailApi(props.id);
        // editBook = res.data;
        for(let key in editBook){
            editBook[key] = res.data[key];
        }

    } catch (err) {
        console.log("服务器出错",err);
    }
}

console.log("props",props);

watch(props,()=>{
    console.log("props.id变了");
    getBookDetail();
},{deep:true,immediate:true})

const emit = defineEmits(['close', "ok"]);

// 表单验证的规则
const rules = reactive({
    "id": [
        { required: true, message: '请输入书号', trigger: 'blur' }
    ],
    "name": [
        { required: true, message: '请输入书名', trigger: 'blur' }
    ],
    "author": [
        { required: true, message: '请输入作者', trigger: 'blur' }
    ],
    "price": [
        { required: true, message: '请输入价格', trigger: 'blur' }
    ],
    "img": [
        { required: true, message: '请输入图片地址', trigger: 'blur' }
    ],
    "type": [
        { required: true, message: '请输入类型', trigger: 'blur' }
    ],
})

const editBookFn = (formEl) => {
    if (!formEl) {
        return;
    }

    formEl.validate((isOk) => {
        if (isOk) {
            editBookApi(props.id,editBook)
                .then(res => {
                    console.log(res);
                    if (res.data) {
                        alert("修改成功!");
                        // 关闭弹窗
                        emit("ok");
                    }
                })
                .catch(err => {

                })
        }
    })


}

const cancelFn = () => {
    emit('close');
}


</script>

4、补充【api和axios封装】:api/crud.js;utils/serviceMock.js

api/crud.js

import service from "@/utils/serviceMock.js";


// 获取所有书籍
export const getBooksApi = ()=>service.get('/books');

// 根据编号获取书籍详情
export const getBookDetailApi = (id)=>service.get('/books/'+id);

// 查询书籍
export const getBooksByCondationApi = (params)=>service.get('/books',{params});

// 删除书籍
export const deleteBookApi = (id)=>service.delete('/books/'+id);


// 添加书籍
export const addBookApi = (data)=>service.post('/books',data);


// 修改书籍
export const editBookApi = (id,data)=>service.put('/books/'+id,data);


// 获取书籍类型
export const getBookTypeApi = ()=>service.get('/bookType');

utils/serviceMock.js
import axios from 'axios';
import store from '@/store';


const service = axios.create({
    baseURL:"http://localhost:3000"
})

// 请求拦截器:所有请求的公共业务
service.interceptors.request.use(config=>{
    store.commit("showLoading");
    return config;
})


// 响应拦截器
service.interceptors.response.use((res)=>{
    store.commit("hideLoading");
    // loading.close();
    return res;
})



export default service;

5、mock数据,用json-server

{
      "books": [
    {
      "id": "878912",
      "name": "水浒1",
      "author": "施耐庵",
      "price": 51.5,
      "img": "/src/assets/imgs/01.jpg",
      "type": "hot"
    },
    {
      "id": "878913",
      "name": "红楼梦",
      "author": "曹雪芹2",
      "price": 51.8,
      "img": "/src/assets/imgs/01.jpg",
      "type": "hot"
    },
    {
      "id": "878917",
      "name": "论语1",
      "author": "王锐1",
      "price": "5.38",
      "img": "/imgs/img3.jpg",
      "type": "new"
    },
    {
      "id": "878918",
      "name": "老子",
      "author": "李家恒",
      "price": 54.8,
      "img": "/imgs/img4.jpg",
      "type": "new"
    },
    {
      "id": "878919",
      "name": "孟子2",
      "author": "李家恒",
      "price": 54.8,
      "img": "/images/img4.jpg",
      "type": "new"
    },
    {
      "id": "878920",
      "name": "孟子3",
      "author": "李家恒",
      "price": 54.8,
      "img": "/images/img4.jpg",
      "type": "new"
    },
    {
      "id": "878921",
      "name": "孟子4",
      "author": "李家恒",
      "price": 54.8,
      "img": "/images/img4.jpg",
      "type": "new"
    },
    {
      "id": "878922",
      "name": "孟子5",
      "author": "李家恒",
      "price": 54.8,
      "img": "/images/img4.jpg",
      "type": "new"
    },
    {
      "id": "878923",
      "name": "孟子6",
      "author": "李家恒",
      "price": 54.8,
      "img": "/images/img4.jpg",
      "type": "new"
    },
    {
      "id": "01008",
      "name": "霸道总裁爱上我",
      "author": "曹宇",
      "price": "9.9",
      "img": "/src/imgs/01.jpg",
      "type": "hot"
    },
    {
      "id": "01009",
      "name": "西厢记",
      "author": "赵蕊",
      "price": "10.9",
      "img": "/src/assets/imgs/01.jpg",
      "type": "hot"
    },
    {
      "id": "01010",
      "name": "钢铁是怎样炼成的",
      "author": "奥斯特洛夫斯基",
      "price": "11.9",
      "img": "/src/assets/imgs/02.jpg",
      "type": "hot"
    },
    {
      "id": "01011",
      "name": "12",
      "author": "22",
      "price": 0,
      "img": "1",
      "type": "hot"
    },
    {
      "id": "01012",
      "name": "假如我是亿万富翁",
      "author": "金莉",
      "price": "1000",
      "img": "/src/assets/imgs/01.jpg",
      "type": "new"
    }
  ],
}                         

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

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

相关文章

Ubuntu使用Nginx部署前端项目——记录

安装nginx 依次执行以下两条命令进行安装&#xff1a; sudo apt-get update sudo apt-get install nginx通过查看版本号查看是否安装成功&#xff1a; nginx -v补充卸载操作&#xff1a; sudo apt-get remove nginx nginx-common sudo apt-get purge nginx nginx-common su…

为计算机设计一个完美的思维模型,帮找bug和漏洞,一起来做渗透测试吧 最赚钱的10种思维模型

芒格 如果我不能淘汰自己一年前的思维模型&#xff0c;这一年我就白过了。&#xff08;终身学习&#xff0c;不断迭代自己。&#xff09; 思维模型是什么&#xff0c;有哪些&#xff1f; 思维模型是用来简化和理解复杂现实世界的概念框架。它们是一种思考和解决问题的工具&a…

8个最流行的Revit插件【2023-2024】

NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 Revit 已取代 AutoCAD 成为全球行业标准软件。 随着设计复杂性的增加&#xff0c;近年来插件变得更加必要。 热…

【腾讯地图】【微信小程序】地图选点

【相关文章】 【腾讯地图】【微信小程序】地图选点 【腾讯地图】【微信小程序】路线规划 【腾讯地图】【微信小程序】城市记录&#xff08;基于地图选点入门版&#xff09; 【效果展示】 【官方文档】 微信小程序插件-地图选点插件 【完善流程】 当前操作和官方文档操作有部…

06 # 枚举类型

一个角色判断例子 function initByRole(role) {if (role 1 || role 2) {// do sth} else if (role 3 || role 4) {// do sth} else if (role 5) {// do sth} else {// do sth} }上面的代码存在的问题&#xff1a; 可读性差&#xff1a;很难记住数字的含义可维护性差&…

前端笔记:React的form表单全部置空或者某个操作框置空的做法

原创/朱季谦 在React框架前端开发中&#xff0c;经常会有弹出框的开发&#xff0c;涉及到弹出框&#xff0c;难免就会有表单。一般在关闭弹出框或者对表单联动时&#xff0c;往往都需要考虑对表单进行置空操作了。 我以前在工作就遇到过这类问题&#xff0c;正好顺便对表单置空…

Linux RN6752 驱动编写

一、概述 关于 RN6752V1 这个芯片这里就不做介绍了&#xff0c;看到这篇笔记的小伙伴应该都明白&#xff0c;虽然说 RN6752V1 芯片是 AHD 信号的解码芯片&#xff0c;但是也可以把芯片当做是一个 YUV 信号的 MIPI 摄像头&#xff0c;所以驱动的编写和 MIPI 摄像头无太大的区别。…

Docker篇之docker部署harbor仓库

一、首先需要安装docker step1&#xff1a;安装docker #1、安装yun源 yum install -y yum-utils #2、配置yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 如果上面源不稳定的话&#xff0c;更换为下列的aliyun源 yu…

爬虫学习 逆向爬虫(六)

多任务异步协程 协程:更高效的利用CPU import timedef func():print("黎明")time.sleep(3)print("还是黎明")func() 等待时机长 sleep时CPU不再工作 IO操作(费时不费力)->阻塞 线程运行阻塞后 移出主线程 移动到下一个 4个任务一个线程 …

首次部署Linux系统的经历

我是一名电子信息工程专业的学生&#xff0c;有次在图书馆上自习的时候无意间看到其他同学的电脑屏幕&#xff0c;黑色的屏幕上显示着一行一行的代码&#xff0c;勾起了我无限的好奇&#xff0c;经过询问得知他是用的Linux操作系统&#xff0c;是和Windows完全不同的系统&#…

Python解释器和环境变量配置(超详细)

一、 python解释器下载 1.百度python官网并打开 官网网址&#xff1a;www.python.org/ 在这里插入图片描述 2.选择DownLoads&#xff0c;Windows并打开 3.在下图页面选择你需要的版本下载即可&#xff08;本文以python 3.10.4版本演示&#xff09; 在这里插入图片描述 二、安…

基于OpenCV的手势识别系统设计与开发

摘要 随着计算机技术与信息处理技术迅速发展&#xff0c;智能化电子设备逐渐进入到日常的生产和生活中&#xff0c;与此同时&#xff0c;人们对电子设备操作过程的便捷化也提出了新的要求&#xff0c;这也促使计算机进行图像处理的技术也得到了发展。近些年兴起的模式识别技术…

蓝桥杯每日一题2023.11.29

题目描述 #include <stdio.h> #include <string.h>void StringInGrid(int width, int height, const char* s) {int i,k;char buf[1000];strcpy(buf, s);if(strlen(s)>width-2) buf[width-2]0;printf("");for(i0;i<width-2;i) printf("-"…

unity UI特效遮罩

using System.Collections; using System.Collections.Generic; using UnityEngine;/**UI特效遮罩 1.需要将ScrollRect 的遮罩Mask 换为 2D Mask2.将特效的Render里面的 Masking 设置为*/ public class UIParticleMaskControll : MonoBehaviour {// Start is called before …

《HelloGitHub》第 92 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 …

手敲myarraylist,深入了解其运行逻辑

1、自定义MyArrayList类 该类里面基本有两个属性&#xff0c;一个是用来存放数据的数组&#xff0c;另外一个是用来描述已经存放数据的数量。同时设置arraylist表的默认长度为10&#xff1b;代码如下&#xff1a; public class MyArrayList {private int[] elem;private int u…

基于matlab的图像去噪算法设计与实现

摘 要 随着我们生活水平的提高&#xff0c;科技产品飞速更新换代&#xff0c;在信息传输中&#xff0c;图像传输所占的比重越来越大。但自然噪声会在图像传输时干扰其传输过程&#xff0c;甚至会使图片不能表达其原来的意义。去噪处理就是为了去除图像中的噪声&#xff0c;从而…

出口贸易媒体发稿7种方法提升转化率的秘密武器解析-华媒舍

出口贸易成为了许多企业发展的重要方向。在这个竞争激烈的市场中&#xff0c;如何让自己的产品脱颖而出&#xff0c;吸引更多客户并提高转化率&#xff0c;成为了每个企业家都面临的挑战。本文将向大家介绍7种提升转化率的秘密武器&#xff1a;出口贸易媒体发稿方法。 1. 出口贸…

如何获取1688的订单详情

获取1688订单详情需要申请 第一步&#xff1a;先去1688-开放平台申请&#xff0c;申请不一定能通过&#xff0c;审批很严。 第二步&#xff1a;首次登录请先注册&#xff0c;注册成功后即可登录。 第三步&#xff1a;选择&#xff1a;我是第三方开发者 第三方是封装好的ap…

如何判断数据库慢 SQL 查询?

慢 SQL 查询通常指执行时间较长或者消耗大量系统资源的查询。要判断一个 SQL 查询是否慢&#xff0c;可以考虑以下几个方面&#xff1a; 执行时间&#xff1a; 观察查询执行所需的时间。如果一个查询花费了相对较长的时间才能返回结果&#xff0c;可能就是慢查询的一个指标。通…