Vue 3 + Element Plus + Spring Boot + MyBatis实现前后端分离计算器

目录

 作业信息

项目链接

0 PSP表格

1 设计实现过程

2 成品展示

1 基础计算器

1 基础运算

2 错误提示

3 读取历史

4 清零回退

5 科学计算

6 原型设计

7 显示最近十条记录

8 扩展功能

分数四则运算​编辑

多重函数嵌套​编辑

2 利率计算器

1 计算存贷款利息

2 前端修改存贷款利息

3 利率设置

3 主要代码说明

前端:App.vue

利率计算器部分

利率配置对话框

使用aniox作为请求工具

后端

提供接口

处理跨域请求

映射数据库中的表

4 心路历程与收获


 作业信息

Calculator
这个作业属于哪个课程https://bbs.csdn.net/forums/ssynkqtd-05
这个作业要求在哪里https://bbs.csdn.net/topics/617377308
这个作业的目标实现前后端分离计算器
其他参考文献...

项目链接

前端

后端

0 PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划3010
Estimate估计这个任务需要多少时间2010
Development开发500600
Analysis需求分析(包括学习新技术)4001800
Design Spec生成设计文档2030
Design Review设计复审3020
Coding Standard代码规范(为目前的开发制定的规划)2060
Design具体设计3070
Coding具体编码6001050
Code Review代码复审6020
Test测试(自我测试,修改代码并提交)120160
Reporting报告60180
Test Repor测试报告2020
Size Measurement计算工作量3020
Postmorten&Process 事后总结,并提出过程改进计划3030
合计20704080

1 设计实现过程

功能结构图:

工具介绍

  • 前端: 使用Vue 3 + Element Plus, 并使用 axios 库进行网络请求与后端进行数据交互,使用VSCode
  • 后端: 使用 SpringBoot SpringMVC 和 Mybatis,对应端点请求和数据库交互 使用通用Mapper TKMapper 简化数据库操作,使用IDEA
  • 数据库:使用 MySQL 来存储历史记录和利率信息,并通过 MyBatis 来进行数据库操作,用navicat可视化。

2 成品展示

1 基础计算器

1 基础运算

2 错误提示

3 读取历史

4 清零回退

5 科学计算

6 原型设计

计算器设计图如下:

        设计参考百度计算器和360计算器,且观察到百度计算器和360计算器点击函数会返回函数加括号,如点击cos,返回cos( , 这样可以简化用户操作,更加直观,便于用户计算复杂的表达式,故参考了此设计,演示视频如下。

7 显示最近十条记录

在后端数据库中调取最近十条记录进行展示。展示界面和数据库信息如下:

8 扩展功能

分数四则运算
多重函数嵌套

2 利率计算器

1 计算存贷款利息

2 前端修改存贷款利息

在前端进行存贷款利率的修改,后端数据库数据也会相应变化。

演示视频如下:

3 利率设置

参照作业二中给出的两个表格进行利率设置,设置如下

3 主要代码说明

前端:App.vue

由于代码较多,故只选取了部分展示,代码中均有注释。

利率计算器部分

使用el-table组件 绑定 rateAList 实时显示利率并再为每一行提供编辑和删除两个按钮,分别绑定 editRow deleteRow方法,执行对应逻辑,因为添加调用的方法是同一个 故传入 1 2 区分添加的是贷款利率还是存款利率

<!-- 利率计算器部分 -->
    <el-tab-pane label="利率计算器" name="second1">
      <div
        style="
          width: 500px;
          height: 500px;
          display: flex;
          flex-direction: column;
          padding: 20px 20px;
          background-color: #fff;
          box-shadow: 0 0 200px -200px #000;
        "
      >
        <!-- 内容输入框 通过此处输入 金额 时长 以供下面功能操作 -->
        <el-form label-width="80">
          <el-form-item label="金额">
            <el-input v-model="amount" />
          </el-form-item>
          <el-form-item label="时长/年">
            <el-input v-model="time" />
          </el-form-item>
        </el-form>

        <!-- 两个按钮 提供 计算 贷款 计算存款的功能入口 调用 calculateHandle 执行逻辑 -->
        <div style="display: flex">
          <el-button type="primary" @click="calculateHandle(1)"
            >计算贷款</el-button
          >
          <el-button
            style="margin-left: 20px"
            @click="calculateHandle(2)"
            type="primary"
            >计算存款</el-button
          >
        </div>

        <!-- 结果显示 绑定 amountResult rateResult strDescResult 实时显示计算结果 -->
        <h3>利息为:{{ amountResult }}元</h3>
        <h3>计算利率为:{{ rateResult }}%,时长描述为:{{ strDescResult }}</h3>
      </div>
    </el-tab-pane>

    <!-- 利率设置部分 -->
    <el-tab-pane label="利率设置" name="second">
      <div style="display: flex; justify-content: space-around">
        <!-- 贷款利率部分 与计算历史实现逻辑相似 使用el-table组件 绑定 rateAList 实时显示贷款利率
				并再每一行提供 编辑 和 删除按钮 分别绑定 editRow deleteRow 方法 执行对应逻辑
				 -->
        <div style="width: 46%">
          <h1>贷款利率</h1>
          <el-table :data="rateAList" style="width: 100%">
            <el-table-column prop="strDesc" label="描述"></el-table-column>
            <el-table-column prop="time" label="时间/年"></el-table-column>
            <el-table-column prop="rate" label="利率"></el-table-column>
            <el-table-column label="操作">
              <template #default="{ row }">
                <el-button-group>
                  <el-button size="small" @click="editRow(row)">编辑</el-button>
                  <el-button size="small" type="danger" @click="deleteRow(row)"
                    >删除</el-button
                  >
                </el-button-group>
              </template>
            </el-table-column>
          </el-table>
          <el-button
            type="primary"
            style="width: 100%; margin-top: 20px"
            @click="add(1)"
            >添加</el-button
          >
        </div>

        <!-- 同贷款利率 因为添加调用的方法是同一个 所以 传入 1 2 区分添加的贷款利率还是存款利率  -->
        <div style="width: 46%">
          <h1>存款利率</h1>
          <el-table :data="rateBList" style="width: 100%">
            <el-table-column prop="strDesc" label="描述"></el-table-column>
            <el-table-column prop="time" label="时间/年"></el-table-column>
            <el-table-column prop="rate" label="利率"></el-table-column>
            <el-table-column label="操作">
              <template #default="{ row }">
                <el-button-group>
                  <el-button size="small" @click="editRow(row)">编辑</el-button>
                  <el-button size="small" type="danger" @click="deleteRow(row)"
                    >删除</el-button
                  >
                </el-button-group>
              </template>
            </el-table-column>
          </el-table>
          <el-button
            type="primary"
            style="width: 100%; margin-top: 20px"
            @click="add(2)"
            >添加</el-button
          >
        </div>
      </div>
    </el-tab-pane>
  </el-tabs>

利率配置对话框

绑定 dialogFormVisible 实现显示和隐藏此对话框,可添加和修改利率内容


  <el-dialog v-model="dialogFormVisible" title="利率配置" align-center="center">
    <el-form :model="form" label-width="80">
      <el-form-item label="时长描述">
        <el-input v-model="form.strDesc" />
      </el-form-item>
      <el-form-item label="时长/年">
        <el-input v-model="form.time" />
      </el-form-item>
      <el-form-item label="利率">
        <el-input v-model="form.rate" />
      </el-form-item>
    </el-form>

    <!-- 操作区 -->
    <template #footer>
      <span class="dialog-footer">
        <!-- 关闭调用 reset 方法 -->
        <el-button @click="reset()">关闭</el-button>

        <!-- 点击确定后 执行 添加 或 修改 逻辑 -->
        <el-button type="primary" @click="confirm()"> 确定 </el-button>
      </span>
    </template>
  </el-dialog>

使用aniox作为请求工具

import axios from "axios";
// el loading 提供加载动画 elmessagebox 提供 确认框 elmessage 提供消息提醒功能
import { ElLoading, ElMessageBox, ElMessage } from "element-plus";
// 后端链接地址
const baseUrl = "http://localhost:8083";
// 加载动画的样式 
const loadingObj = {
  lock: true,
  text: "Loading",
  background: "rgba(255, 255, 255, 0.4)",
};
const headers = {
  headers: {
    "Content-Type": "application/json",
  },
};
import { ref, reactive } from "vue";
const dialogFormVisible = ref(false);

// 对话框中内容的绑定 存储变量 对话框中输入数据 会自动绑定到 form 变量中
const form = reactive({});
// reset 方法 执行时 将 对话框中的内容全部重置为空 并隐藏对话框
const reset = () => {
  Object.assign(form, {
    id: undefined,
    strDesc: undefined,
    time: undefined,
    rate: undefined,
    createtime: undefined,
    type: undefined,
  });

  // 此行代码代表隐藏对话框
  dialogFormVisible.value = false;
};

// 确认 对话框确认方法
const confirm = () => {
  // 首先关闭 对话框
  dialogFormVisible.value = false;

  // 调用elloading 将页面进入 加载状态
  const loading = ElLoading.service(loadingObj);
  console.log(form);

  // 判断 form 变量id是否存在 不存在则代表是创建逻辑 存在则代表更新逻辑
  if (form.id) {
    // 更新逻辑 通过 axios 请求 updatehistory 端点 使后端执行更新历史的逻辑代码
    // 此地需要传输json格式参数 所以 使用 了 headers 变量
    axios
      .post(baseUrl + "/updateHistory", form, headers)
      .then((response) => {
        // 请求响应时 关闭加载动画
        loading.close();

        // 刷新 页面内容
        refreshPage();
      })
      .catch((error) => {
        // 请求失败时 页面提示错误提示
        errorMessage.value = "error";
      });
  } else {
    // 添加逻辑 通过请求 addInterestrate 使后端执行添加利率的逻辑 headers 与更新一致
    axios
      .post(baseUrl + "/addInterestRate", form, headers)
      .then((response) => {
        // 关闭加载动画 刷新页面内容
        loading.close();
        refreshPage();
      })
      .catch((error) => {
        // 请求错误 错误提醒
        errorMessage.value = "error";
      });
  }
};

        由于代码较多,界面样式以及基础计算器等部分未展示,可以查看代码文件,代码均有详细注释。

后端

提供接口

controller.java提供与计算器历史记录和利率相关的接口

提供了以下接口:

  • queryHistory:查询计算器历史,按时间倒序排列,只返回前 10 条历史记录。
  • sendHistory:保存计算器历史,将公式和计算时间保存到数据库中。
  • addInterestRate:添加利率,将利率信息保存到数据库中。
  • deleteInterestRate:删除利率,根据收益率 ID 从数据库中删除对应的收益率信息。
  • queryInterestRate:查询利率,按创建时间升序排列,返回所有的收益率信息。
  • updateHistory:更新利率,根据收益率 ID 更新对应的收益率信息。

使用了Lombok 提供的注解简化代码,如用 @Slf4j 注解生成的 slf4j 日志对象,@RequiredArgsConstructor 注解生成 final 字段构造器。使用 MyBatis 提供的操作数据库的 Mapper 对象来实现数据的增删改查。


// 所有端点接口
@RestController
@Slf4j
@RequiredArgsConstructor
public class Controller {
//    计算器历史数据库操作类
    private final HistoryMapper historyMapper;
//    利率数据库操作类
    private final InterestRateMapper interestRateMapper;
//    查询计算历史
    @GetMapping("/queryHistory")
    public Object queryHistory() {
//        查询 history表 按照时间排序
        Example example = new Example(History.class);
        example.orderBy("time").desc();
        List<History> histories = historyMapper.selectByExample(example);
//        只显示10条
        return histories.stream().limit(10).collect(Collectors.toList());
    }
    // 保存计算历史 将公式保存到 history表
    @PostMapping("/sendHistory")
    public Object sendHistory(@RequestBody History history) {
// 给该数据 设置 当前计算时间
        history.setTime(new Date());
//        保存到数据表
        historyMapper.insert(history);
        return "ok";
    }
    // 添加利率
    @PostMapping("/addInterestRate")
    public Object addInterestRate(@RequestBody InterestRate rate) {
        // 利率添加时间
        rate.setCreatetime(new Date());
        // 保存
        interestRateMapper.insert(rate);
        return "ok";
    }
    // 删除利率
    @PostMapping("/deleteInterestRate")
    public Object deleteInterestRate(String id) {
        // 从数据库中删除
        interestRateMapper.deleteByPrimaryKey(id);
        return "ok";
    }
    // 查询利率
    @PostMapping("/queryInterestRate")
    public Object queryInterestRate() {
//        按照 时间 排序 利率
        Example example = new Example(InterestRate.class);
        example.orderBy("createtime").asc();
//        查询后响应前端
        return interestRateMapper.selectByExample(example);
    }
//    更新利率
    @PostMapping("/updateHistory")
    public Object updateHistory(@RequestBody InterestRate rate) {
        // 从数据库中更新利率
        interestRateMapper.updateByPrimaryKey(rate);
        return "ok";
    }

}

处理跨域请求

Spring MVC 中,默认情况下,浏览器限制了跨域请求,只能向同源的 URL 发送请求。为了允许跨域请求,需进行相应的配置。

 MvcConfiguration 是一个实现了 WebMvcConfigurer 接口的类,通过重写其中的 addInterceptors 方法来添加一个拦截器。

CorsInterceptor 是一个自定义的拦截器,用于处理跨域请求。它会将跨域请求中的跨域资源共享相关的响应标头添加到 HTTP 响应中。

// 跨域设置 将该设置应用到 WebMvcConfigurer 设置
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CorsInterceptor()).addPathPatterns("/**").order(0);
    }
}
public class CorsInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String origin = request.getHeader("Origin");
        if (StringUtils.isBlank(origin)) {
            return true;
        }
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Origin", origin);
        response.setHeader("Access-Control-Allow-Headers", "*");
        return true;
    }

}

映射数据库中的表


// history 表对应的实体类
@Data
@Table(name = "calculator_history")
public class History {

    @Id
    // 表id
    private Integer id;


    // 公式
    private String str;

    // 结果
    private String result;

//    时间 查询出来后 响应前端时 自动格式化
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "Asia/Shanghai")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
    private Date time;

}
// 利率表对应的实体类

@Data
@Table(name = "calculator_interest_rate")
public class InterestRate {

    @Id
    // 表id
    private Integer id;

    // 利率描述
    @Column(name = "str_desc")
    private String strDesc;

    // 时间 年限
    private String time;

    // 利率
    private String rate;

    // 创建时间
    private Date createtime;

    // 类型 存款 贷款
    private String type;

}

还有一些配置文件以及初始化数据库表的代码,由于较长,这里不再展示。

4 心路历程与收获

        之前虽然也学过java,前端,mysql,但是知识点比较分散,缺乏系统的体系化的学习,也缺乏对一个完整的前后端分离的项目的理解与实践。为实现这个前后端分离的计算器以及让界面好看些,故新学了一些框架,Vue3+Element Plus和Spring Boot,MyBatis等,还是挺好用的,就是代码可能稍微有点繁琐,不过界面确实比第一次用python实现的那个计算器好看太多了,也算是很有收获。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值