提醒:
如果前端小伙伴没有看懂这里一些逻辑和功能什么意思的,建议先去看我另一个帖子,里面详细注释用前端听得懂的话说了一遍后端的创建项目后各个文件是干什么用的,以及接口返回数据等逻辑,看了你再来看这个就会明白了。哪里说的很详细了,这里有些就不详细再说一遍了。如果看完了还是不理解可以问,我会的话就跟你说。
帖子:
【前端写java接口】前端用java写一个简单的后端接口并和前端交互数据【以前端角度解释,详细注释,谁都看得懂】
如果不知道实体类是啥的,可以理解成就是前端的对象。
流程逻辑解释:
用前端听的懂的大白话说,就是这个功能分4个步骤完成,首先创建映射数据库的实体类HistoryRecord,然后再创建一个需要返回给前端的实体类HistoryRecordList,然后我们创建一个前端接口文件HistoryRecordController
前端调用后,我们通过这个接口方法调用后端链接数据库的接口文件HistoryRecordMapper查询数据库数据并返回值,然后我们把值都一个个的塞到提前准备好的实体类HistoryRecordList内,然后把这个实体类返回给前端,搞定。
这里解释一下:
(这个返回前端的实体类HistoryRecordList,比如我直接返回数据库查询结果给前端,那么返回值只有一个数组,也就是数据库查出来的表格数据。但是前端需要的不仅仅是表格数据,还需要分页的信息,比如总数,当前页,每页数等等之类的额外信息,那么我们返回的数据不能直接在数据库的实体类里添加字段,所以我们就直接从新建立一个实体类,写好总数,当前页,每页数,表格数据几个变量。然后把我们查到的对应的数据全部存在这一个实体类里面,然后把这个实体类返回给前端就可以达到返回的数据对象内既有表格数据又有页数之类的信息。)
拿到的数据格式
表格分页效果图
文件结构
user的不用管,这是我自己写的另一个。看HistoryRecord开头的就行
代码
HistoryRecord
映射数据库的实体类,字段要一模一样才行。
package com.example.demo.entity;
//历史记录表
import lombok.Data;
@Data
public class HistoryRecord {
private int id;
private String suject;
private String time;
private String name;
private int content;
private int video;
private int knowledge;
private int simulation;
private int exam;
public HistoryRecord() {
}
public HistoryRecord(Integer id, String suject, String time, String name, Integer content, Integer video, Integer knowledge, Integer simulation, Integer exam) {
this.id = id;
this.suject = suject;
this.time = time;
this.name = name;
this.content = content;
this.video = video;
this.knowledge = knowledge;
this.simulation = simulation;
this.exam = exam;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSuject() {
return suject;
}
public void setSuject(String suject) {
this.suject = suject;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getContent() {
return content;
}
public void setContent(Integer content) {
this.content = content;
}
public Integer getVideo() {
return video;
}
public void setVideo(Integer video) {
this.video = video;
}
public Integer getKnowledge() {
return knowledge;
}
public void setKnowledge(Integer knowledge) {
this.knowledge = knowledge;
}
public Integer getSimulation() {
return simulation;
}
public void setSimulation(Integer simulation) {
this.simulation = simulation;
}
public Integer getExam() {
return exam;
}
public void setExam(Integer exam) {
this.exam = exam;
}
}
HistoryRecordList
package com.example.demo.entity;
import lombok.Data;
import java.util.List;
@Data
//传给前端的分页实体类
public class HistoryRecordList {
//总条数
private int total;
//表格数据
private List list;
//当前页
private int currentPage;
//每页数
private int pageSize;
public HistoryRecordList() {
}
public HistoryRecordList(int total, List list, int currentPage, int pageSize) {
this.total = total;
this.list = list;
this.currentPage = currentPage;
this.pageSize = pageSize;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
}
HistoryRecordController
package com.example.demo.controller;
import com.example.demo.entity.HistoryRecord;
import com.example.demo.entity.HistoryRecordList;
import com.example.demo.mapper.HistoryRecordMapper;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/HistoryRecord")
public class HistoryRecordController {
@Resource
HistoryRecordMapper HistoryRecordMapper;
@CrossOrigin(origins ="*",maxAge = 3600)
@GetMapping("/select")
//前端get请求发进来两个参数,分别为,当前页currentPage,每页数pageSize
public HistoryRecordList findHistoryRecord(@RequestParam("currentPage") int currentPage,@RequestParam("pageSize") int pageSize){
//这里套用别人帖子里解释的一段话让我一下子想明白了这个查询语句的写法,写在这里希望你们看了也能恍然大明白。
//MySql实现分页查询的SQL语句
//分页需求:
//客户端通过传递currentPage(页码),pageSize(每页显示的条数)两个参数去分页查询数据库表中的数据,那我们知道MySql数据库提供了分页的函数limit m,n,但是该函数的用法和我们的需求不一样,
// 所以就需要我们根据实际情况去改写适合我们自己的分页语句,具体的分析如下:
//比如:
//查询第1条到第10条的数据的sql是:select * from history_record limit 0,10; ->对应我们的需求就是查询第一页的数据:select * from history_record limit (1-1)*10,10;
//
//查询第10条到第20条的数据的sql是:select * from history_record limit 10,20; ->对应我们的需求就是查询第二页的数据:select * from history_record limit (2-1)*10,10;
//
//查询第20条到第30条的数据的sql是:select * from history_record limit 20,30; ->对应我们的需求就是查询第三页的数据:select * from history_record limit (3-1)*10,10;
//按照公式(currentPage-1)*pageSize先用变量保存当前页(这里三元表达式是因为有个小bug,如果用户点击的不是第一页,而是在第二页或者其他页的时候调整每页显示的条数就会出先一次查不到数据的bug。原因是没有从第一页开始查。所以我们这里三元表达式做个限定,如果用户点击每页数从默认的10条改变的时候,直接把页数调整成从第一页第一条开始查)
int cuIndex=pageSize==10?(currentPage-1)*pageSize:0*pageSize;
//调用数据库的方法返回的表格数据用数组保存
List list=HistoryRecordMapper.HistoryRecordAll(cuIndex,pageSize);
//存下当前页
int currentPageIndex=currentPage;
//存下每页数
int pageSizeIndex=pageSize;
//调用数据库表格总数方法返回的值存下来
int totalIndex=HistoryRecordMapper.HistoryRecordIndex();
//new出要返回给前端的对象,不new出对象无法往里面赋值
HistoryRecordList historyRecordList=new HistoryRecordList();
//往对象内list添加表格数据
historyRecordList.setList(list);
//把当前页赋值进去
historyRecordList.setCurrentPage(currentPageIndex);
//把每页数赋值进去
historyRecordList.setPageSize(pageSizeIndex);
//把总数赋值进去
historyRecordList.setTotal(totalIndex);
//对象的数据上面赋值都拿到了,返回整个对象给前端
return historyRecordList;
}
}
HistoryRecordMapper
package com.example.demo.mapper;
import com.example.demo.entity.HistoryRecord;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface HistoryRecordMapper {
//搜索数据库分页对应数据
@Select("select * from history_record limit #{currentPage},#{pageSize}")
List<HistoryRecord> HistoryRecordAll(@Param("currentPage") int currentPage, @Param("pageSize") int pageSize);
//搜索数据库数据总条数
@Select("SELECT count(*) FROM history_record")
int HistoryRecordIndex();
}
结束:
//我不是做后端的哈,我也是前端的。也没系统学过,就是网上花几天时间看了看java基础语法,
然后就开始靠着百度一步步尝试功能,写出了一些简单的小功能,然后保持我总结分析的习惯,
把功能写成笔记在这,方便我以后用的时候可以直接看就能看懂。
也方便其他前端小伙伴想写一写后端的时候可以不用再踩一次我踩过的坑。毕竟你不系统学一遍后端,
基础不牢,百度很多后端发的功能实现帖子都看不懂,因为他们发帖不会把最基础的东西解释给你听,
默认是你基础都会得。
//我前端还不熟悉的时候也被很多前端的帖子看的晕头转向,因为前端发帖也是不会跟你说基础问题的,
直接功能实现,现在我看很轻松了,以前看也很艰难,所以我一直有个习惯,
就是把一些功能详细的从基础一句句注释解释出来发帖,方便以后我忘了或其他前端新人可以看得懂,少点折磨
前端的代码要看的也可以看看
<template>
<div class="release_wrap">
<div class="release_title">个 人 信 息</div>
<el-card class="release_card">
<el-button
type="primary"
round
icon="el-icon-arrow-left"
style="margin-bottom: 40px"
@click="jump_home"
>返回</el-button
>
<div>
<el-input
placeholder="请输入查询内容"
v-model="input"
clearable
style="width: 300px"
>
</el-input>
<el-button type="primary" style="margin-left: 20px">查询</el-button>
<el-tag type="success" style="margin-left: 540px">{
{
"已通过: " + exam_total
}}</el-tag>
<el-tag type="danger" style="margin-left: 20px">{
{
"未通过: " + nopass_total
}}</el-tag>
<el-tag type="info" style="margin-left: 20px">{
{
"科目总数: " + tableData.length + "/" + 188
}}</el-tag>
</div>
<el-table :data="tableData" style="width: 100%" max-height="600">
<el-table-column
prop="suject"
label="科目"
width="380"
show-overflow-tooltip
>
</el-table-column>
<el-table-column prop="time" label="学习时间" width="280">
</el-table-column>
<el-table-column prop="name" label="人员"> </el-table-column>
<el-table-column label="业务内容">
<template slot-scope="scope">
<el-button type="success" size="small" v-if="scope.row.content == 1"
>已学习</el-button
>
<el-button size="small" type="primary" v-else>未学习</el-button>
</template>
</el-table-column>
<el-table-column label="业务视频">
<template slot-scope="scope">
<el-button type="success" size="small" v-if="scope.row.video == 1"
>已学习</el-button
>
<el-button size="small" type="primary" v-else>未学习</el-button>
</template>
</el-table-column>
<el-table-column label="知识点">
<template slot-scope="scope">
<el-button
type="success"
size="small"
v-if="scope.row.knowledge == 1"
>已学习</el-button
>
<el-button size="small" type="primary" v-else>未学习</el-button>
</template>
</el-table-column>
<el-table-column label="模拟训练">
<template slot-scope="scope">
<el-button
type="success"
size="small"
v-if="scope.row.simulation == 1"
>已学习</el-button
>
<el-button size="small" type="primary" v-else>未学习</el-button>
</template>
</el-table-column>
<el-table-column label="业务考试">
<template slot-scope="scope">
<el-button type="success" size="small" v-if="scope.row.exam == 1"
>已通过</el-button
>
<el-button size="small" type="danger" v-else>未通过</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top:15px"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage"
:page-sizes="[10, 20, 30, 40]"
:page-size="pagesize"
layout="total, sizes, prev, pager, next"
:total="totalindex"
>
</el-pagination>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
//表格数据
tableData: [],
//查询的输入框
input: "",
//当前页码
currentPage: 1,
//每页数
pagesize:10,
//总数
totalindex:0
};
},
computed: {
exam_total() {
let a = this.tableData.filter(function (x, y) {
return x.exam == 1;
}).length;
return a;
},
pass_total() {
let b = this.tableData.filter(function (x, y) {
return x.state == 2;
}).length;
return b;
},
nopass_total() {
let c = this.tableData.filter(function (x, y) {
return x.exam == 0;
}).length;
return c;
},
},
created() {
this.getDataList();
},
methods: {
//页数
handleSizeChange(val) {
this.pagesize=val;
this.getDataList()
console.log(`每页 ${
val} 条`);
},
//当前页
handleCurrentChange(val) {
this.currentPage=val;
this.getDataList()
console.log(`当前页: ${
val}`);
},
//提交按钮
onSubmit() {
console.log(this.dynamicTags, "dynamicTags");
},
//返回首页
jump_home() {
this.$router.push("/");
},
//已学习·
jump_material(row) {
console.log(row);
},
//获取表格数据
getDataList() {
this.$axios.get("/HistoryRecord/select",{
currentPage:this.currentPage,
pageSize:this.pagesize
}).then((res) => {
this.tableData = res.list;
this.totalindex=res.total
console.log(res);
});
},
},
};
</script>
<style scoped lang='scss'>
.release_wrap {
background-image: url("../assets/home1.jpg");
width: 100%;
height: 100%;
position: relative;
}
//卡片效果
.release_card {
width: 70%;
position: absolute;
top: 200px;
left: 50%;
transform: translateX(-50%);
box-shadow: 0 0.3px 0.7px rgba(0, 0, 0, 0.126),
0 0.9px 1.7px rgba(0, 0, 0, 0.179), 0 1.8px 3.5px rgba(0, 0, 0, 0.224),
0 3.7px 7.3px rgba(0, 0, 0, 0.277), 0 10px 20px rgba(0, 0, 0, 0.4);
transition: 0.5s ease; //改变大小
&:hover {
box-shadow: 0 0.7px 1px rgba(0, 0, 0, 0.157),
0 1.7px 2.6px rgba(0, 0, 0, 0.224), 0 3.5px 5.3px rgba(0, 0, 0, 0.28),
0 7.3px 11px rgba(0, 0, 0, 0.346), 0 20px 30px rgba(0, 0, 0, 0.5);
}
}
.el-tag + .el-tag {
margin-left: 10px;
}
.button-new-tag {
margin-left: 10px;
height: 32px;
line-height: 30px;
padding-top: 0;
padding-bottom: 0;
}
.input-new-tag {
width: 90px;
margin-left: 10px;
vertical-align: bottom;
}
// title效果
.release_title {
text-align: center;
font-size: 38px;
font-weight: bold;
position: absolute;
top: 75px;
left: 50%;
transform: translateX(-50%);
font-family: Lato, sans-serif; //字体
letter-spacing: 4px; //字符间距空白
text-transform: uppercase; //转换文本,控制大小写
background: linear-gradient(
90deg,
rgba(0, 0, 0, 1) 0%,
rgba(255, 255, 255, 1) 50%,
rgba(0, 0, 0, 1) 100%
);
background-size: 80%; //背景大小
background-repeat: no-repeat; //背景平铺不重复
// below two lines create text gradient effect
color: rgba(237, 227, 231, 0.7); //颜色透明
background-clip: text; //规定背景的绘制区域在文字上
animation: shining 3s linear infinite;
}
@keyframes shining {
from {
background-position: -500%; //背景图像的起始位置
}
to {
background-position: 500%; //背景图像的结束位置
}
}
</style>