文章目录

  • 一、环境搭建
  • 二、用户管理页面(纯展示无事件操作)
    • 0.三步走
    • 1.查询表单
      • (1)书写页面代码 :
      • (2)对应的js部分创建对象数据模型的绑定部分:
      • (3)引入需要的库/依赖:
      • (4)效果展示
    • 2.显示增删改查的按钮
      • (1)书写页面代码 :
      • (2)不需要创建对象的原因
      • (3)引入需要的库/依赖:
      • (4)效果展示
    • 3.会员信息的数据表格展示
      • (1)书写页面代码 :
      • (2)对应的js部分创建对象数据模型的绑定部分:
      • (3)引入需要的库/依赖:
      • (4)效果展示
    • 4.分页条展示
      • (1)书写页面代码 :
      • (2)对应的js部分创建对象数据模型的绑定部分:
      • (3)引入需要的库/依赖:
      • (4)效果展示
  • 三、前端发送请求+事件操作+后端响应
    • 1.页面加载的时候实现数据展示和分页效果
    • 2.重置功能 :
    • 3.查询会员(完成条件查询)
    • 4.删除功能
    • 5.新增功能
    • 6.修改功能
  • 四、增删改查的全部代码+前后端响应思路
    • 1.全部代码
    • 2.前后端分离项目的响应思路
      • 1.前端发送请求
      • 2.后端接收请求
      • 3.后端做出响应
      • 4.前端处理响应
      • 5.常见问题以及解决方案
      • 6.总结

一、环境搭建

项目搭建可以参考上篇博客:

https://blog.csdn.net/m0_72900498/article/details/150282255?spm=1001.2014.3001.5501

二、用户管理页面(纯展示无事件操作)

想要实现的大致效果:
在这里插入图片描述

即整个三面html是四个部分:查询条件的表单,创建修改删除查询等按钮、用于显示成员信息的表格、分页条。

先写出大体的区域框架结构。

在这里插入图片描述

Element-plus:
https://element-plus.org/zh-CN/component/table.html

0.三步走

三步骤 :写网页(复制粘贴自己改造 )、创建对象(根据具体 情况分析 ) 、引入相关库/依赖 (网站上面都提供了)自己按照需要修改即可
在这里插入图片描述
根据需要选择自己需要的样式即可,然后下面还有需要引入的库,一定要引入进去 ,不然无法生效

在这里插入图片描述
是否需要创建对象,创建对象的格式网站也已经在对应的地方提供:比如:
在这里插入图片描述

1.查询表单

Element-plus:
https://element-plus.org/zh-CN/component/form.html

在这里插入图片描述
想作为查询条件的是:ID、手机号、姓名、年龄、性别、地址 、出生日期范围

(1)书写页面代码 :

<!-- 查询条件区域:想作为查询条件的是:ID、姓名、手机号、性别、年龄、地址 、出生日期范围--><div class="page-container"><!--行内样式、双向绑定数据模型formInline.prop:和后端字段绑定--><el-form :inline="true" :model="formInline" ><el-form-item label="ID" prop="id"><el-input v-model="formInline.id" placeholder="请输入客户ID" style="width: 130px" clearable/></el-form-item><el-form-item label="姓名" prop="name"><el-input v-model="formInline.name" placeholder="请输入客户姓名" style="width: 160px" clearable/></el-form-item><el-form-item label="电话" prop="phone"><el-input v-model="formInline.phone" placeholder="请输入客户电话" clearable/></el-form-item><el-form-item label="性别"  prop="sex"  style="width: 120px"><el-selectv-model="formInline.sex"clearable><el-option label="不限" value="不限"  /><el-option label="" value="" /><el-option label="" value="" /></el-select></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="formInline.age" placeholder="请输入客户年龄" clearable/></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="formInline.address" placeholder="请输入客户地址" clearable/></el-form-item><el-form-item label="出生日期"><el-date-pickerv-model="formInline.birthdayRange"type="daterange"start-placeholder="起始日期"end-placeholder="终止日期"/></el-form-item></el-form></div>

(2)对应的js部分创建对象数据模型的绑定部分:

// 查询表单对象:双向绑定数据:浏览器输入(视图 )-数据模型:
//因为这个表单是接收数据的,所以我们创建对象的时候就要定义变量并且完成初始化操作。
let formInline = ref({id:null,name:null,phone:null,sex:null,age:null,address:null,birthdayRange:[]
})

(3)引入需要的库/依赖:

import { ref, onMounted } from 'vue'
import api from "@/utils/api.js";

上述部分目前的全部代码:

<template><!-- 查询条件区域:想作为查询条件的是:ID、姓名、手机号、性别、年龄、地址 、出生日期范围--><div class="page-container"><!--行内样式、双向绑定数据模型formInline.prop:和后端字段绑定--><el-form :inline="true" :model="formInline" ><el-form-item label="ID" prop="id"><el-input v-model="formInline.id" placeholder="请输入客户ID" style="width: 130px" clearable/></el-form-item><el-form-item label="姓名" prop="name"><el-input v-model="formInline.name" placeholder="请输入客户姓名" style="width: 160px" clearable/></el-form-item><el-form-item label="电话" prop="phone"><el-input v-model="formInline.phone" placeholder="请输入客户电话" clearable/></el-form-item><el-form-item label="性别"  prop="sex"  style="width: 120px"><el-selectv-model="formInline.sex"clearable><el-option label="不限" value="不限"  /><el-option label="" value="" /><el-option label="" value="" /></el-select></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="formInline.age" placeholder="请输入客户年龄" clearable/></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="formInline.address" placeholder="请输入客户地址" clearable/></el-form-item><el-form-item label="出生日期"><el-date-pickerv-model="formInline.birthdayRange"type="daterange"start-placeholder="起始日期"end-placeholder="终止日期"/></el-form-item></el-form></div><!-- 按钮区--><div></div><!--  表格展示成员数据--><div></div><!--  分页条:--><div></div>
</template><!--CSS样式-->
<style></style><!--JS事件操作部分 :-->
<<script setup>
import { ref, onMounted } from 'vue'
import api from "@/utils/api.js";// 查询表单对象:双向绑定数据:浏览器输入(视图 )-数据模型:
//因为这个表单是接收数据的,所以我们创建对象的时候就要定义变量并且完成初始化操作。
let formInline = ref({id:null,name:null,phone:null,sex:null,age:null,address:null,birthdayRange:[]
})onMounted(async () => {let resp = await api({url: "members",//http://localhost:3000/api/后面实际解析的时候是http://localhost:8080/api/v1/membersmethod: "get",params: {page: 1,limit: 10}});console.log(resp);
});
</script>

(4)效果展示

在这里插入图片描述

2.显示增删改查的按钮

https://element-plus.org/zh-CN/component/button.html

(1)书写页面代码 :

<!-- 按钮区--><div><div class="mb-4"><el-button type="primary" round>增加会员</el-button><el-button type="success" round>修改会员</el-button><el-button type="info" round>查询会员</el-button><el-button type="danger" round>删除会员</el-button></div></div>

(2)不需要创建对象的原因

不需要再跟上面的表单一样去创建对象,原因
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)引入需要的库/依赖:

(4)效果展示

在这里插入图片描述

3.会员信息的数据表格展示

https://element-plus.org/zh-CN/component/table.html

(1)书写页面代码 :

<!-- 3.表格展示成员数据--><div><el-table:data="tableData"style="width: 100%"class="data-grid"borderhighlight-current-rowshow-header:header-cell-style="{background: '#E6A23C',color: 'white',fontWeight: 'bold',stripe}"><el-table-column type="selection" width="160" align="center" fixed/><el-table-column fixed prop="id" label="会员ID" width="160"/><el-table-column fixed prop="name" label="姓名" width="130"/><el-table-column prop="phone" label="电话" width="150"/><el-table-column prop="age" label="年龄" width="120"/><el-table-column prop="createTime" label="注册时间" width="180"/><el-table-column prop="address" label="地址" width="250"/><el-table-column prop="sex" label="性别" width="120"/><el-table-column prop="remark" label="备注" width="260"/><el-table-column prop="birthday" label="出生日期" min-width="180"/></el-table></div>

并添加CSS样式:

<!--CSS样式-->
<style>
.data-grid {margin-top: 6px;
}
</style>

(2)对应的js部分创建对象数据模型的绑定部分:

//3.数据显示表格对象 :
const tableData = ref()

(3)引入需要的库/依赖:

import { ref } from 'vue'

(4)效果展示

在这里插入图片描述

4.分页条展示

https://element-plus.org/zh-CN/component/pagination.html

(1)书写页面代码 :

  <!-- 4.分页条--><div class="pagination"><el-paginationv-model:current-page="memberPi.pageNo"v-model:page-size="memberPi.pageSize":page-sizes="[1,5,10,15,20]"layout="total, sizes, prev, pager, next, jumper":total="memberPi.total"class="member-pi"background@current-change="handlePageChange"@size-change="handleSizeChange"/></div>

(2)对应的js部分创建对象数据模型的绑定部分:

//4.分页条对象 :里面的数据是默认值
let memberPi = reactive({//reactive也是一个响应式对象 这个访问的时候不用.valuepageNo: 1,pageSize: 10,total: 0
});

(3)引入需要的库/依赖:

import { ref } from 'vue'
import { reactive } from 'vue' // 必须导入 reactive

(4)效果展示

在这里插入图片描述

至此,基本的页面展示部分已经做完了。整体效果 :
在这里插入图片描述

然后剩下的就是从数据库查询数据响应给前端了。

三、前端发送请求+事件操作+后端响应

1.页面加载的时候实现数据展示和分页效果

具体实现:

(1)首先给 查询会员按钮 添加事件:也就是添加查询 方法

在这里插入图片描述

<!-- 2.按钮区--><div><div class="mb-4"><el-button type="primary" round>增加会员</el-button><el-button type="success" round>修改会员</el-button><el-button type="info" round @click="select()">查询会员</el-button><el-button type="danger" round>删除会员</el-button></div></div>

(2)自定义查询方法 : 当组件挂载完毕之后触发:这样一打开页面就有数据

//当组件挂载完毕之后触发:这样一打开页面就有数据
onMounted(async () => {select();
});

具体的select()方法以及分页查询的实现:

// 查询方法
async function select(pageNo = 1, pageSize = 10) {let params = toRaw(formInline.value);if(params.birthdayRange) {params.birthdayFrom = params.birthdayRange[0];params.birthdayTo = params.birthdayRange[1];delete params.birthdayRange;}console.log(params);try {const resp = await api({url: "/members",method: "get",params: {pageNo,pageSize,...params}});tableData.value = resp.data.records;memberPi.pageNo = resp.data.current;memberPi.pageSize = resp.data.size;memberPi.total = resp.data.total;} catch (error) {console.error("查询失败:", error);}
}
// 分页变化处理
const handlePageChange = (currentPage) => {memberPi.pageNo = currentPage;select(currentPage, memberPi.pageSize);
};const handleSizeChange = (pageSize) => {memberPi.pageSize = pageSize;select(1, pageSize);
};

实现效果 :
在这里插入图片描述

上述效果的汇总代码

<template><!-- 1.查询条件区域:想作为查询条件的是:ID、姓名、手机号、性别、年龄、地址 、出生日期范围--><div class="page-container"><!--行内样式、双向绑定数据模型formInline.prop:和后端字段绑定--><el-form :inline="true" :model="formInline"><el-form-item label="ID" prop="id"><el-input v-model="formInline.id" placeholder="请输入客户ID" style="width: 130px" clearable/></el-form-item><el-form-item label="姓名" prop="name"><el-input v-model="formInline.name" placeholder="请输入客户姓名" style="width: 160px" clearable/></el-form-item><el-form-item label="电话" prop="phone"><el-input v-model="formInline.phone" placeholder="请输入客户电话" clearable/></el-form-item><el-form-item label="性别" prop="sex" style="width: 160px"><el-select v-model="formInline.sex" clearable><el-option label="不限" value="不限"/><el-option label="" value=""/><el-option label="" value=""/></el-select></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="formInline.age" placeholder="请输入客户年龄" clearable/></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="formInline.address" placeholder="请输入客户地址" clearable/></el-form-item><el-form-item label="出生日期"><el-date-pickerv-model="formInline.birthdayRange"type="daterange"start-placeholder="起始日期"end-placeholder="终止日期"/></el-form-item></el-form></div><!-- 2.按钮区--><div><div class="mb-4"><el-button type="primary" round>增加会员</el-button><el-button type="success" round>修改会员</el-button><el-button type="info" round @click="select()">查询会员</el-button><el-button type="danger" round>删除会员</el-button></div></div><!-- 3.表格展示成员数据--><div><el-table:data="tableData"style="width: 100%"class="data-grid"borderhighlight-current-rowshow-header:header-cell-style="{background: '#E6A23C',color: 'white',fontWeight: 'bold',stripe}"><el-table-column type="selection" width="160" align="center" fixed/><el-table-column fixed prop="id" label="会员ID" width="160"/><el-table-column fixed prop="name" label="姓名" width="130"/><el-table-column prop="phone" label="电话" width="150"/><el-table-column prop="age" label="年龄" width="120"/><el-table-column prop="createTime" label="注册时间" width="180"/><el-table-column prop="address" label="地址" width="250"/><el-table-column prop="sex" label="性别" width="120"/><el-table-column prop="remark" label="备注" width="260"/><el-table-column prop="birthday" label="出生日期" min-width="180"/></el-table></div><!-- 4.分页条--><div class="pagination"><el-paginationv-model:current-page="memberPi.pageNo"v-model:page-size="memberPi.pageSize":page-sizes="[1,5,10,15,20]"layout="total, sizes, prev, pager, next, jumper":total="memberPi.total"class="member-pi"background@current-change="handlePageChange"@size-change="handleSizeChange"/></div>
</template><script setup>
import { reactive, ref, onMounted, toRaw } from 'vue'
import api from "@/utils/api.js";const size = ref('default');
const disabled = ref(false);// 查询表单对象
let formInline = ref({id: null,name: null,phone: null,sex: null,age: null,address: null,birthdayRange: []
});// 表格数据对象:响应式对象
let tableData = ref([]);// 分页配置
let memberPi = reactive({pageNo: 1,pageSize: 10,total: 0
});// 查询方法
async function select(pageNo = 1, pageSize = 15) {let params = toRaw(formInline.value);if(params.birthdayRange) {params.birthdayFrom = params.birthdayRange[0];params.birthdayTo = params.birthdayRange[1];delete params.birthdayRange;}console.log(params);try {const resp = await api({url: "/members",method: "get",params: {pageNo,pageSize,...params}});tableData.value = resp.data.records;memberPi.pageNo = resp.data.current;memberPi.pageSize = resp.data.size;memberPi.total = resp.data.total;} catch (error) {console.error("查询失败:", error);}
}// 分页变化处理
const handlePageChange = (currentPage) => {memberPi.pageNo = currentPage;select(currentPage, memberPi.pageSize);
};const handleSizeChange = (pageSize) => {memberPi.pageSize = pageSize;select(1, pageSize);
};// 组件挂载时加载数据
onMounted(() => {select();
});
</script><style>
.data-grid {margin-top: 6px;
}.pagination {margin-top: 20px;display: flex;justify-content: center;
}
</style>

2.重置功能 :

(1)添加重置按钮并绑定事件

  <!-- 2.按钮区--><div><div class="mb-4"><el-button type="primary" round>增加会员</el-button><el-button type="success" round>修改会员</el-button><el-button type="info" round @click="select()">查询会员</el-button><el-button type="primary" round @click="reset">重置</el-button><el-button type="danger" round>删除会员</el-button></div></div>

关于上面绑定事件,绑定方法加不加 ()的区别 :

简单理解就是需要传递参数加();
不需要传递参数不加 ()

//重置按钮:重置表单操作:将表单的值设为空即可
function reset() {formInline.value = {id: null,name: null,phone: null,sex: null,age: null,address: null,birthdayRange: []};
}

3.查询会员(完成条件查询)

逻辑是:当我们点击查询会员按钮的时候,能够通过不同的非空查询条件查询出来对应的会员信息。

首先前端传递的都是字符串,先将日期格式进行转换 :
在表单的出生日期 部分添加:

value-format="YYYY-MM-DD"

我们在页面加载部分显示会员信息数据部分已经给出了具体的实现

实现效果 :

在这里插入图片描述
这部分重点是前端 传递参数 ,后端正确的 接收到,更多问题 其实是 出现在了后端,后端响应部分的代码 :
https://blog.csdn.net/m0_72900498/article/details/150282255?spm=1001.2014.3001.5501

4.删除功能

(1)给表格添加ref创建实例:

// 声明表格引用
const tableRef = ref()

添加到表格里面:属性 部分:

ref="tableRef"

引入依赖:

import { ElMessage, ElMessageBox } from 'element-plus' // 必须添加

(2)给删除按钮绑定事件(方法)

//删除会员按钮:实现只选中一行数据
function remove() {let rows = tableRef.value.getSelectionRows();//通过实例获取选中的表格的是哪一行 if (rows.length === 0) {ElMessage.warning("请选中您要删除的行");//设置提示信息} else {ElMessageBox.confirm("是否确认删除选中的行?", "警告", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning"}).then(() => {//执行操作let ids = rows.map(it => it.id);//获取选中的删除IdremoveByIds(ids);//校验只选中一行成功之后,调用removeByIds方法真正删除,并传递要删除的会员的Id值}).catch(() => {//捕获之后 });}
}
async function removeByIds(ids) {let resp = await api({url: "/members",method: "delete",data: ids});if (resp.success) {ElMessage.success("删除操作成功,共删除" + resp.data + "条");select(); // 刷新表格} else {ElMessage.error("删除失败,请稍候再试或联系管理员");}
}

点击选中行事件:


function tblRowClick(row) {if (!row || !tableRef.value) returntableRef.value.toggleRowSelection(row)
}

效果:
在这里插入图片描述
具体的删除操作去数据库中查 :

servcie层方法

package com.study.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import java.util.List;public interface MemberService {//查询全部客户Page<Member> findAll(Page<Member> page, MemberSearchBean msb);//删除操作:批量删除(多个--传集合:是客户Id也就是整型),返回受影响的行数int delete(List<Integer> ids);
}
package com.study.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import java.util.List;public interface MemberService {//查询全部客户Page<Member> findAll(Page<Member> page, MemberSearchBean msb);//删除操作:批量删除(多个--传集合:是客户Id也就是整型),返回受影响的行数int delete(List<Integer> ids);
}

根据Id删除mybatis-plus底层已经提供了,直接调方法就行,所以不用写mapper层了

Controller层:

package com.study.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import com.study.service.MemberService;
import com.study.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("api/v1/members" )//接收前端的请求,路径与前端发送请求的路径一致
public class MemberController {private MemberService memberService;@Autowired//依赖注入:创建对象:public void setMemberService(MemberService memberService) {this.memberService = memberService;}//查询全部客户:@GetMappingpublic ResponseEntity<JsonResult<?>> findAll(@RequestParam(defaultValue = "1") Integer pageNo,@RequestParam(defaultValue = "15") Integer pageSize,MemberSearchBean msb){Page<Member> page = new Page<>(pageNo,pageSize);Page<Member> all = memberService.findAll(page, msb);return ResponseEntity.ok(JsonResult.success(all));}@DeleteMapping//删除操作public ResponseEntity<JsonResult<?>> delete(@RequestBody Integer[] ids){int count = memberService.delete(List.of(ids));if(count==0){return ResponseEntity.ok(JsonResult.fail("删除会员失败"));}else {return ResponseEntity.ok(JsonResult.success(count));}}
}

Service层:

package com.study.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import java.util.List;public interface MemberService {//查询全部客户Page<Member> findAll(Page<Member> page, MemberSearchBean msb);//删除操作:批量删除(多个--传集合:是客户Id也就是整型),返回受影响的行数int delete(List<Integer> ids);
}
package com.study.service.impl;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.mapper.MemberMapper;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import com.study.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;@Service//控制反转:创建对象
public class MemberServiceImpl implements MemberService {@Autowiredprivate MemberMapper memberMapper;@Overridepublic Page<Member> findAll(Page<Member> page, MemberSearchBean msb) {return memberMapper.findAll(page,msb);}@Overridepublic int delete(List<Integer> ids) {return memberMapper.deleteByIds(ids);//注意选对方法}}

在这里插入图片描述
效果:
在这里插入图片描述
在这里插入图片描述

5.新增功能

(1)点击新增按钮出现弹窗:也就是对话框
按照官网给的就行:

https://element-plus.org/zh-CN/component/dialog.html
在这里插入图片描述
在这里插入图片描述
都有,根据需要改就行了。

 <!--  5-增加会员:--><div><el-dialog v-model="dialogVisible" title="新增会员信息" width="500" draggable><el-form-item label="ID" prop="id" v-if="false"><el-input v-model="formInline2.id" placeholder="请输入ID" style="width: 130px" clearable/></el-form-item><el-form-item label="姓名" prop="name"><el-input v-model="formInline2.name" placeholder="请输入客户姓名" style="width: 160px" clearable/></el-form-item><el-form-item label="电话" prop="phone"><el-input v-model="formInline2.phone" placeholder="请输入客户电话" clearable/></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="formInline2.age" placeholder="请输入客户年龄" clearable/></el-form-item><el-form-item label="注册时间"><el-date-pickerv-model="formInline2.createTime"type="date"placeholder="注册日期"value-format="YYYY-MM-DD"/></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="formInline2.address" placeholder="请输入客户地址" clearable/></el-form-item><el-form-item label="性别" prop="sex" style="width: 160px"><el-select v-model="formInline2.sex" clearable><el-option label="" value=""/><el-option label="" value=""/></el-select></el-form-item><el-form-item label="备注" prop="remark" :rows="4"><el-input v-model="formInline2.remark"width="260px" placeholder="请输入客户信息备注" clearable/></el-form-item><el-form-item label="出生日期"><el-date-pickerv-model="formInline2.birthday"type="date"placeholder="出生日期"value-format="YYYY-MM-DD"/></el-form-item><template #footer><div class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="submitAdd">确定</el-button></div></template></el-dialog></div>

在这里插入图片描述

这个弹窗成功显示了,且能够正常填写数据,接下来就是给确定和取消按钮 添加事件 ,当点击确定按钮的时候提交后台。

但是要先添加输入信息是否合法的校验:暂时不做,后面再完善

相关事件:

// 对话框控制
const dialogVisible = ref(false)
// 新增会员表单数据
let formInline2 = ref({id: null,name: null,phone: null,sex: null,age: null,address: null,birthday:null,createTime: null,remark: null
});

后端完成响应。

6.修改功能

// 对话框控制:修改页面
const dialogVisible2 = ref(false)
<el-dialog v-model="dialogVisible2" title="修改会员信息" width="500" draggable><el-form :model="formInline3"><el-form-item label="ID" prop="id" v-if="false"><el-input v-model="formInline3.id" placeholder="请输入ID" style="width: 130px" clearable/></el-form-item><el-form-item label="姓名" prop="name"><el-input v-model="formInline3.name" placeholder="请输入客户姓名" style="width: 160px" clearable/></el-form-item><el-form-item label="电话" prop="phone"><el-input v-model="formInline3.phone" placeholder="请输入客户电话" clearable/></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="formInline3.age" placeholder="请输入客户年龄" clearable/></el-form-item><el-form-item label="注册时间"><el-date-pickerv-model="formInline3.createTime"type="date"placeholder="注册日期"value-format="YYYY-MM-DD"/></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="formInline3.address" placeholder="请输入客户地址" clearable/></el-form-item><el-form-item label="性别" prop="sex" style="width: 160px"><el-select v-model="formInline3.sex" clearable><el-option label="" value=""/><el-option label="" value=""/></el-select></el-form-item><el-form-item label="备注" prop="remark" :rows="4"><el-input v-model="formInline3.remark"width="260px" placeholder="请输入客户信息备注" clearable/></el-form-item><el-form-item label="出生日期"><el-date-pickerv-model="formInline3.birthday"type="date"placeholder="出生日期"value-format="YYYY-MM-DD"/></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="dialogVisible2 = false">取消</el-button><el-button type="primary" @click="submitEdit">确定</el-button></div></template></el-dialog></div>
// 修改会员表单数据
let formInline3 = ref({id: null,name: null,phone: null,sex: null,age: null,address: null,birthday:null,createTime: null,remark: null
});

在这里插入图片描述

后端完成响应即可

四、增删改查的全部代码+前后端响应思路

1.全部代码

<template><!-- 1.查询条件区域:想作为查询条件的是:ID、姓名、手机号、性别、年龄、地址 、出生日期范围--><div class="page-container"><!--行内样式、双向绑定数据模型formInline.prop:和后端字段绑定--><el-form :inline="true" :model="formInline"><el-form-item label="ID" prop="id"><el-input v-model="formInline.id" placeholder="请输入ID" style="width: 130px" clearable/></el-form-item><el-form-item label="姓名" prop="name"><el-input v-model="formInline.name" placeholder="请输入客户姓名" style="width: 160px" clearable/></el-form-item><el-form-item label="电话" prop="phone"><el-input v-model="formInline.phone" placeholder="请输入客户电话" clearable/></el-form-item><el-form-item label="性别" prop="sex" style="width: 160px"><el-select v-model="formInline.sex" clearable><el-option label="不限" value="不限"/><el-option label="" value=""/><el-option label="" value=""/></el-select></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="formInline.age" placeholder="请输入客户年龄" clearable/></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="formInline.address" placeholder="请输入客户地址" clearable/></el-form-item><el-form-item label="出生日期"><el-date-pickerv-model="formInline.birthdayRange"type="daterange"start-placeholder="起始日期"end-placeholder="终止日期"value-format="YYYY-MM-DD"/></el-form-item></el-form></div><!-- 2.按钮区--><div><div class="mb-4"><el-button type="primary" round @click="openAddDialog">增加会员</el-button><el-button type="success" round  @click="edit">修改会员</el-button><el-button type="info" round @click="select()">查询会员</el-button><el-button type="primary" round @click="reset">重置</el-button><el-button type="danger" round @click="remove">删除会员</el-button></div></div><!-- 3.表格展示成员数据--><div><el-table ref="tableRef" :data="tableData" style="width: 100%" class="data-grid"@row-click="tblRowClick()"  stripeborder highlight-current-row show-header :header-cell-style="{background: '#5da6e6',color: 'white',fontWeight: 'bold',}"><el-table-column type="selection" width="160" align="center" fixed height="160" name="custom-selection-col" /><el-table-column fixed prop="id" label="会员ID" width="160" height="230px"/><el-table-column fixed prop="name" label="姓名" width="130"/><el-table-column prop="phone" label="电话" width="150"/><el-table-column prop="age" label="年龄" width="120"/><el-table-column prop="createTime" label="注册时间" width="180"/><el-table-column prop="address" label="地址" width="250"/><el-table-column prop="sex" label="性别" width="120"/><el-table-column prop="remark" label="备注" width="260"/><el-table-column prop="birthday" label="出生日期" min-width="180"/></el-table></div><!-- 4.分页条--><div class="pagination"><el-paginationv-model:current-page="memberPi.pageNo"v-model:page-size="memberPi.pageSize":page-sizes="[1,5,10,15,20]"layout="total, sizes, prev, pager, next, jumper":total="memberPi.total"class="member-pi"background@current-change="handlePageChange"@size-change="handleSizeChange"/></div><!--  5-增加会员:--><div><el-dialog v-model="dialogVisible" title="新增会员信息" width="500" draggable><el-form-item label="ID" prop="id" v-if="false"><el-input v-model="formInline2.id" placeholder="请输入ID" style="width: 130px" clearable/></el-form-item><el-form-item label="姓名" prop="name"><el-input v-model="formInline2.name" placeholder="请输入客户姓名" style="width: 160px" clearable/></el-form-item><el-form-item label="电话" prop="phone"><el-input v-model="formInline2.phone" placeholder="请输入客户电话" clearable/></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="formInline2.age" placeholder="请输入客户年龄" clearable/></el-form-item><el-form-item label="注册时间"><el-date-pickerv-model="formInline2.createTime"type="date"placeholder="注册日期"value-format="YYYY-MM-DD"/></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="formInline2.address" placeholder="请输入客户地址" clearable/></el-form-item><el-form-item label="性别" prop="sex" style="width: 160px"><el-select v-model="formInline2.sex" clearable><el-option label="" value=""/><el-option label="" value=""/></el-select></el-form-item><el-form-item label="备注" prop="remark" :rows="4"><el-input v-model="formInline2.remark"width="260px" placeholder="请输入客户信息备注" clearable/></el-form-item><el-form-item label="出生日期"><el-date-pickerv-model="formInline2.birthday"type="date"placeholder="出生日期"value-format="YYYY-MM-DD"/></el-form-item><template #footer><div class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="submitAdd">确定</el-button></div></template></el-dialog></div><!--  6-修改会员:--><div><el-dialog v-model="dialogVisible2" title="修改会员信息" width="500" draggable><el-form :model="formInline3"><el-form-item label="ID" prop="id" v-if="false"><el-input v-model="formInline3.id" placeholder="请输入ID" style="width: 130px" clearable/></el-form-item><el-form-item label="姓名" prop="name"><el-input v-model="formInline3.name" placeholder="请输入客户姓名" style="width: 160px" clearable/></el-form-item><el-form-item label="电话" prop="phone"><el-input v-model="formInline3.phone" placeholder="请输入客户电话" clearable/></el-form-item><el-form-item label="年龄" prop="age"><el-input v-model="formInline3.age" placeholder="请输入客户年龄" clearable/></el-form-item><el-form-item label="注册时间"><el-date-pickerv-model="formInline3.createTime"type="date"placeholder="注册日期"value-format="YYYY-MM-DD"/></el-form-item><el-form-item label="地址" prop="address"><el-input v-model="formInline3.address" placeholder="请输入客户地址" clearable/></el-form-item><el-form-item label="性别" prop="sex" style="width: 160px"><el-select v-model="formInline3.sex" clearable><el-option label="" value=""/><el-option label="" value=""/></el-select></el-form-item><el-form-item label="备注" prop="remark" :rows="4"><el-input v-model="formInline3.remark"width="260px" placeholder="请输入客户信息备注" clearable/></el-form-item><el-form-item label="出生日期"><el-date-pickerv-model="formInline3.birthday"type="date"placeholder="出生日期"value-format="YYYY-MM-DD"/></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="dialogVisible2 = false">取消</el-button><el-button type="primary" @click="submitEdit">确定</el-button></div></template></el-dialog></div>
</template><script setup>
import { reactive, ref, onMounted, toRaw } from 'vue'
import api from "@/utils/api.js";
import { ElMessage, ElMessageBox } from 'element-plus'const size = ref('default');
const disabled = ref(false);// 对话框控制:新增页面
const dialogVisible = ref(false)
// 对话框控制:修改页面
const dialogVisible2 = ref(false)// 查询表单对象
let formInline = ref({id: null,name: null,phone: null,sex: null,age: null,address: null,birthdayRange: []
});// 表格数据对象
let tableData = ref([]);// 分页配置
let memberPi = reactive({pageNo: 1,pageSize: 15,total: 0
});// 新增会员表单数据
let formInline2 = ref({id: null,name: null,phone: null,sex: null,age: null,address: null,birthday:null,createTime: null,remark: null
});// 修改会员表单数据
let formInline3 = ref({id: null,name: null,phone: null,sex: null,age: null,address: null,birthday:null,createTime: null,remark: null
});// 查询会员方法
async function select(pageNo = 1, pageSize = 15) {let params = toRaw(formInline.value);if(params.birthdayRange) {params.birthdayFrom = params.birthdayRange[0];params.birthdayTo = params.birthdayRange[1];delete params.birthdayRange;}try {const resp = await api({url: "/members",method: "get",params: {pageNo,pageSize,...params}});tableData.value = resp.data.records;memberPi.pageNo = resp.data.current;memberPi.pageSize = resp.data.size;memberPi.total = resp.data.total;} catch (error) {console.error("查询失败:", error);}
}// 分页变化处理
const handlePageChange = (currentPage) => {memberPi.pageNo = currentPage;select(currentPage, memberPi.pageSize);
};const handleSizeChange = (pageSize) => {memberPi.pageSize = pageSize;select(1, pageSize);
};// 重置表单
function reset() {formInline.value = {id: null,name: null,phone: null,sex: null,age: null,address: null,birthday:null};
}// 表格操作
const tableRef = ref()function tblRowClick(row) {if (!row || !tableRef.value) returntableRef.value.toggleRowSelection(row)
}//删除会员按钮:实现只选中一行数据
function remove() {let rows = tableRef.value.getSelectionRows();//通过实例获取选中的表格的是哪一行if (rows.length === 0) {ElMessage.warning("请选中您要删除的行");//设置提示信息} else {ElMessageBox.confirm("是否确认删除选中的行?", "警告", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning"}).then(() => {//执行操作let ids = rows.map(it => it.id);//获取选中的删除IdremoveByIds(ids);//校验只选中一行成功之后,调用removeByIds方法真正删除,并传递要删除的会员的Id值}).catch(() => {//捕获之后});}
}async function removeByIds(ids) {let resp = await api({url: "/members",method: "delete",data: ids});if (resp.success) {ElMessage.success("删除操作成功,共删除" + resp.data + "条");select(); // 刷新表格} else {ElMessage.error("删除失败,请稍候再试或联系管理员");}
}// 打开新增对话框
function openAddDialog() {formInline2.value = {id: null,name: null,phone: null,sex: null,age: null,address: null,birthday:null,createTime: null,remark: null}dialogVisible.value = true
}// 提交新增
async function submitAdd() {try {// 处理日期数据const params = {...toRaw(formInline2.value),birthdayFrom: formInline2.value.birthdayRange?.[0],birthdayTo: formInline2.value.birthdayRange?.[1]}delete params.birthdayRangeconst resp = await api({url: "/members",method: "post",data: params})if (resp.success) {ElMessage.success("新增会员成功")dialogVisible.value = falseselect() // 刷新表格}} catch (error) {console.error("新增失败:", error)ElMessage.error("新增失败,请稍候再试")}
}
//新增表单对象
let memberFormRef = ref();
let mode = "add";//标志位//修改按钮
function edit() {let rows = tableRef.value.getSelectionRows();if (rows.length === 0) {ElMessage.warning("请选中您要修改的行");} else if (rows.length > 1) {ElMessage.warning("您一次只能修改一行");} else {// 将选中的行数据填充到表单中formInline3.value = {...rows[0]};dialogVisible2.value = true;}
}//提交修改
async function submitEdit() {try {const resp = await api({url: "/members",method: "put",data: toRaw(formInline3.value)});if (resp.success) {ElMessage.success("修改会员信息成功");dialogVisible2.value = false;select(); // 刷新表格}} catch (error) {console.error("修改失败:", error);ElMessage.error("修改失败,请稍候再试");}
}
// 组件挂载时加载数据
onMounted(() => {select();
});
</script><style>
.data-grid {margin-top: 6px;
}.pagination {margin-top: 20px;display: flex;justify-content: center;
}.member-pi {margin-top: 6px;
}</style>

2.前后端分离项目的响应思路

在前后端分离架构中,前端(Vue/React)和后端(Spring Boot)通过 RESTful API 进行交互,主要涉及 请求(Request) 和 响应(Response) 的处理。

1.前端发送请求

在这里插入图片描述
前端四种请求方式举例:

// GET 请求(带查询参数)
await api({url: "/members",method: "get",params: { pageNo: 1, pageSize: 10 }
});// POST 请求(提交 JSON 数据)
await api({url: "/members",method: "post",data: { name: "张三", age: 25 }
});// PUT 请求(修改数据,ID 在 URL 中)
await api({url: `/members/${id}`,method: "put",data: { name: "李四", age: 30 }
});// DELETE 请求(删除数据)
await api({url: `/members/${id}`,method: "delete"
});

2.后端接收请求

在这里插入图片描述

@RestController
@RequestMapping("/api/v1/members")
public class MemberController {@GetMappingpublic ResponseEntity<JsonResult<?>> findAll(@RequestParam(defaultValue = "1") int pageNo,@RequestParam(defaultValue = "10") int pageSize) {// 查询逻辑}@PostMappingpublic ResponseEntity<JsonResult<?>> add(@RequestBody Member member) {// 新增逻辑}@PutMapping("/{id}")public ResponseEntity<JsonResult<?>> edit(@PathVariable Integer id,@RequestBody Member member) {// 修改逻辑}@DeleteMapping("/{id}")public ResponseEntity<JsonResult<?>> delete(@PathVariable Integer id) {// 删除逻辑}
}

3.后端做出响应

后端返回响应
统一响应格式(推荐):

{"success": true,"code": 200,"message": "操作成功","data": { ... }  // 业务数据
}

Spring Boot 返回方式:

@GetMapping
public ResponseEntity<JsonResult<?>> findAll() {List<Member> members = memberService.findAll();return ResponseEntity.ok(JsonResult.success(members));
}@PostMapping
public ResponseEntity<JsonResult<?>> add(@RequestBody Member member) {boolean success = memberService.add(member);if (success) {return ResponseEntity.ok(JsonResult.success("新增成功"));} else {return ResponseEntity.ok(JsonResult.fail("新增失败"));}
}

4.前端处理响应

Axios 拦截器(统一处理错误):

// 响应拦截器(api.js)
axios.interceptors.response.use((response) => {if (response.data.success) {return response.data; // 返回 data 部分} else {ElMessage.error(response.data.message || "操作失败");return Promise.reject(response.data);}},(error) => {ElMessage.error(error.response?.data?.message || "网络错误");return Promise.reject(error);}
);

javascript

async function loadMembers() {try {const resp = await api.get("/members");tableData.value = resp.data; // 获取后端返回的 data} catch (error) {console.error("加载失败:", error);}
}

5.常见问题以及解决方案

在这里插入图片描述

6.总结

在这里插入图片描述

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

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

相关文章

在IAR Embedded Workbench for Arm中实现NXP S32K3安全调试

随着汽车电子系统变得越来越智能&#xff0c;对功能安全&#xff08;Safety&#xff09;的要求越来越高&#xff0c;同时信息安全&#xff08;Security&#xff09;也越来越被关注&#xff0c;安全调试&#xff08;Secure Debug&#xff09;机制已成为一个重要的信息安全特性。…

Vue实例中的其他属性【5】

目录1.计算属性&#xff1a;1.概述&#xff1a;2.语法特点&#xff1a;3.案例&#xff1a;案例1&#xff1a;案例2&#xff1a;案例3&#xff1a;4.总结&#xff1a;5.get函数什么时候执行&#xff1f;6.注意:2.监视属性&#xff1a;1.概述&#xff1a; 2.用法&#xff1a;1.监…

C++入门自学Day11-- String, Vector, List 复习

往期内容回顾 List类型的自实现 List类型&#xff08;初识&#xff09; Vector类的自实现 Vector类&#xff08;注意事项&#xff09; 初识Vector String类的自实现 String类的使用&#xff08;续&#xff09; String类&#xff08;续&#xff09; String类&#xff08;初识&…

JavaScript性能优化实战(三):DOM操作性能优化

想象一下&#xff0c;你正在精心布置一个豪华蛋糕&#xff08;你的网页&#xff09;&#xff0c;每次添加一颗草莓&#xff08;DOM元素&#xff09;都要把整个蛋糕从冰箱拿出来、放回去&#xff08;重排重绘&#xff09;&#xff0c;来来回回几十次&#xff0c;不仅效率低下&am…

【力扣】面试经典150题总结02-双指针、滑动窗口

1.验证回文串&#xff08;简单&#xff09;用toLowerCase()转为小写字母&#xff0c;然后前后指针向中间进行比对。2.判断子序列&#xff08;简单&#xff09;两个指针一个指向长字符串&#xff0c;另一个指向短字符串。匹配就都1&#xff0c;不匹配就将长字符串指针1。长字符串…

MQ迁移方案

以下是完整的MQ迁移方案设计&#xff0c;涵盖同构/异构迁移、零丢失保障、灰度切换等关键环节&#xff0c;适用于Kafka、RabbitMQ、RocketMQ等主流消息队列&#xff1a;​一、迁移方案选型矩阵​​场景​​适用方案​​技术实现​​优缺点​​同集群版本升级​滚动重启 协议兼…

RAG 分块中表格填补简明示例:Markdown、HTML、Excel、Doc

表格填补是RAG分块中常见的需求&#xff0c;但不同格式的表格处理方式有所不同。本文将对 Markdown、HTML、Excel 的合并单元格进行说明&#xff0c;并给出 Python 示例&#xff0c;演示如何解析和填补。1. Markdown 表格Markdown 只能用空值表示合并单元格。&#xff08;只有列…

IDEA创建一个VUE项目

由于新手学习VUE&#xff0c;所以使用手动初始化项目 步骤&#xff1a; 创建项目文件夹&#xff1a;在 IDEA 中点击 File > New > Project&#xff0c;选择 Empty Project&#xff0c;指定项目路径。初始化 npm&#xff1a;在终端中&#xff1a;npm init -y安装vue&#…

Chrome插件开发实战:todoList 插件

以下是一个适合小团队自用的 Chrome TodoList 插件开发示例&#xff0c;包含基础功能&#xff08;增删改查、本地存储、统计&#xff09;和简洁的交互设计。代码结构清晰&#xff0c;适合新手学习或快速上手。 一、项目准备 创建插件项目目录 todo-list-extension&#xff0c;…

【Redis数据库开启SSL加密】【小白指南】【生产环境可用】附带Docker服务器配置和python连接Redis数据库代码(加密通讯版)

【Redis数据库开启SSL加密】【填坑指南】附带服务器配置和python连接测试代码 本教程转为小白提供设置Redis安全访问&#xff0c;自签名证书进行安全访问你的Redis数据库&#xff0c;轻松实现安全访问和保护数据库不被非法入侵。 本文原创&#xff0c;转载请注明出处&#xff0…

笔记本电脑键盘失灵【已解决】

配置环境硬件详情笔记本电脑联想拯救者y7000 2019 PG0&#xff08;已更新为win11&#xff09;外接键盘colorful ckb-p100问题今天笔记本开机后&#xff0c;进入登录页面输入密码&#xff0c;突然发现笔记本自带键盘&#xff08;我通常不用外接键盘&#xff09;的键失灵了&#…

postgresql运维问题解决:PG集群备节点状态异常告警处理

小亦平台会持续给大家科普一些运维过程中常见的问题解决案例&#xff0c;运维朋友们可以在常见问题及解决方案专栏查看更多案例 问题概述&#xff1a; 故障&#xff1a; pg数据库备节点状态异常现象&#xff1a; 一般为集群间心跳超时导致,现象为集群有fail-count失败数告警&…

Maven 开发实践

文章目录1. 搭建私服&#xff08;windows)2.上传依赖3.多个远程仓库配置4.其它1. 搭建私服&#xff08;windows) 软件下载 https://help.sonatype.com/en/download.html修改端口 etc/nexus-default.properties启动程序 管理员身份进入进入bin目录下执行.\nexus.exe /run创建Ma…

设计心得——如何架构选型

一、架构的作用 可能对于很多的公司&#xff0c;其实架构本身的重要性并不大。大家一定明白这回事&#xff0c;架构在实际的开发&#xff0c;在大多数的场景下其实用处并没有书籍和资料中讲的那样重要&#xff0c;甚至是可有可无。这样讲是不有些可笑&#xff1f;是不是觉得挺意…

vba学习系列(12)--反射率通过率计算复杂度优化25/8/17

系列文章目录 文章目录系列文章目录前言一、反射率通过率1.整体通过率2.整体通过率3.客户工艺匹配4.机台通过率分析5.镜片通过率罩次分析分析1.1分析1.26.镜片通过率圈数分析分析1.1分析1.28.镜筒通过率圈数分析分析1.1分析1.29.镜筒通过率罩次分析分析1.2总结前言 一、反射率通…

Microsoft WebView2

运行效果 代码如下 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Form…

GitCode 疑难问题诊疗:全方位指南

一、问题诊断与解决框架1.1 通用问题排查流程在面对 GitCode 问题时&#xff0c;遵循一套科学的排查流程至关重要。首先&#xff0c;详细记录问题出现时的具体操作步骤与相关报错信息&#xff0c;这有助于精准定位问题根源。例如&#xff0c;若在执行git push命令时出现错误&am…

AMD Ryzen AI Max+ 395四机并联:大语言模型集群推理深度测试

本文介绍使用四块Framework主板构建AI推理集群的完整过程&#xff0c;并对其在大语言模型推理任务中的性能表现进行了系统性评估。该集群基于AMD Ryzen AI Max 395处理器&#xff0c;采用mini ITX规格设计&#xff0c;可部署在10英寸标准机架中。 Jeff Geerling大佬还开发了名…

深度学习·GFSS

GFSS General Few-Shot Segmentation 任务实现方式与zero-shot有所不同本篇论文只涉及同一个模态(图像)&#xff0c;训练过程中&#xff0c;novel class有几个图像提供&#xff0c;提供k个就称之为k-shot。先从图像中提取class prototype&#xff0c;然后这个原型向量作为查询&…

Transformer架构的数学本质:从注意力机制到大模型时代的技术内核

系列专栏推荐&#xff1a;零基础学Python&#xff1a;Python从0到100最新最全教程 深入浅出讲解神经网络原理与实现&#xff0c;从基础的多层感知机到前沿的Transformer架构。包含完整的数学推导、代码实现和工程优化技巧。 写在前面&#xff1a;为什么理解Transformer如此重要…