核心业务2:借款人申请借款额度

核心业务2:借款人申请借款额度

1.业务流程图

------------提交个人信息--------

2.借款人申请借款额度数据库设计

3.借款人申请额度流程

4.前端代码逻辑

5.后端代码逻辑

------------提交个人信息--------

------------评估积分--------

6.展示用户个人信息后管理员审批流程

7.前端代码逻辑

8.后端代码逻辑

------------评估积分--------
------------审核通过--------

9.展示用户个人信息后管理员修改状态更改积分流程

10.数据库涉及表

11.前端代码逻辑

12.后端代码逻辑

------------审核通过--------

核心业务2:借款人申请借款额度

1.业务流程图

在这里插入图片描述

①用户在注册登陆账户绑定之后,点击立即借款进入到借款认证页

  • A进入到借款认证页后,进入尚融宝判断借款状态来显示步骤
  • B表单中的下拉列表数据在尚融宝查询数据字典获取
  • C在上传照片时利用尚融宝上传数据到aliyun,在删除图片后删除aliyun中数据
  • D点击提交后提交表单到尚融宝更新借款人数据
    在这里插入图片描述

②如果A中已提交未审核则进入审核页

在这里插入图片描述

③如果A中已审核则将结果返回

在这里插入图片描述

2.借款人申请借款额度数据库设计

①用户数据表user_info

在这里插入图片描述

②借款人表borrower

在这里插入图片描述

③借款人绑定表borrower_attach

在这里插入图片描述

④三张表关系

  • user_info通过user_id和borrower的user_id关联
  • borrower的id和borrower_attach的borrow_id关联
  • user_info即如果用户为借款人申请借款额度,用户信息表中包含了该用户为借款人的认证状态。
  • borrower即包含了用户为借款人的基本信息
  • borrower_attach表包含了用户为借款人的四张图片信息(房产证,轿车证,身份证正反面)

3.借款人申请额度流程

①前端

  • 用户注册登陆绑定数据后
  • 第一次借款认证填写信息提交表单
  • 提交后再次访问提交表单页则直接进入认证中或者认证结果

②尚融宝后端

  • 用户访问认证页
  • 判断用户是否认证过,认证的状态。
  • 如果没有认证过则前端显示表单页,后端需要在表单页显示时返回数据字典来初始化表单的下拉列表。
  • 在填写表单时对图片的上传和删除同步到aliyun的oss
  • 在填写完表单之后前端提交表单,后端根据表单数据更新user_info的借款人认证状态,根据token获得user_id以及表单信息来更新borrower和borrower_attach

4.代码逻辑

①前端对应表单对象

在这里插入图片描述

②前端请求接口

  • 判断借款人认证状态
    在这里插入图片描述
  • 请求获取数据字典

在这里插入图片描述

  • 请求上传和删除图片
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 提交表单
    在这里插入图片描述

③前端复杂逻辑

  • 需要完善表单信息。
    文件的表单信息需要上传成功后加入到表单中,如果删除文件,对应的也需要删除表单中的文件(删除文件如果删除表单,组件封装了调用成功后的响应结果)
  • 刚进入认证页会先进入表单页再判断是否认证过,前端就算认证过也会闪过表单。
    修改步骤为null,必须查看认证结果后赋值,不会闪表单

④总体代码

  • pages/user/borrow.vue
<template>
  <div class="personal-main">
    <div class="personal-pay">
      <h3><i>借款人信息认证</i></h3>

      <!--步骤导航-->
      <el-steps :active="active" style="margin: 40px">
        <el-step title="填写借款人信息"></el-step>
        <el-step title="提交平台审核"></el-step>
        <el-step title="等待认证结果"></el-step>
      </el-steps>

      <!--第一步-->
      <div v-if="active === 0" class="user-borrower">
        <!--个人信息-->
        <h6>个人基本信息</h6>
        <el-form label-width="120px">
          <el-form-item label="年龄">
            <el-col :span="5">
              <el-input v-model="borrower.age" />
            </el-col>
          </el-form-item>

          <el-form-item label="性别">
            <el-select v-model="borrower.sex">
              <el-option :value="1" :label="'男'" />
              <el-option :value="0" :label="'女'" />
            </el-select>
          </el-form-item>
          <el-form-item label="婚否">
            <el-select v-model="borrower.marry">
              <el-option :value="true" :label="'是'" />
              <el-option :value="false" :label="'否'" />
            </el-select>
          </el-form-item>
          <el-form-item label="学历">
            <el-select v-model="borrower.education">
              <el-option
                v-for="item in educationList"
                :key="item.value"
                :label="item.name"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="行业">
            <el-select v-model="borrower.industry">
              <el-option
                v-for="item in industryList"
                :key="item.value"
                :label="item.name"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="月收入">
            <el-select v-model="borrower.income">
              <el-option
                v-for="item in incomeList"
                :key="item.value"
                :label="item.name"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="还款来源">
            <el-select v-model="borrower.returnSource">
              <el-option
                v-for="item in returnSourceList"
                :key="item.value"
                :label="item.name"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
        </el-form>
        <!--联系人信息-->
        <h6>联系人信息</h6>
        <el-form label-width="120px">
          <el-form-item label="联系人姓名">
            <el-col :span="5">
              <el-input v-model="borrower.contactsName" />
            </el-col>
          </el-form-item>
          <el-form-item label="联系人手机">
            <el-col :span="5">
              <el-input v-model="borrower.contactsMobile" />
            </el-col>
          </el-form-item>
          <el-form-item label="联系人关系">
            <el-select v-model="borrower.contactsRelation">
              <el-option
                v-for="item in contactsRelationList"
                :key="item.value"
                :label="item.name"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
        </el-form>
        <!--身份认证信息-->
        <h6>身份认证信息</h6>
        <!--其中的module是为了区分每个上传文件的位置在OSS-->
        <el-form label-width="120px">
          <el-form-item label="身份证人像面">
            <el-upload
              :on-success="onUploadSuccessIdCard1"
              :on-remove="onUploadRemove"
              :multiple="false"
              :action="uploadUrl"
              :data="{ module: 'idCard1' }"
              :limit="1"
              list-type="picture-card"
            >
              <i class="el-icon-plus"></i>
            </el-upload>
          </el-form-item>
          <el-form-item label="身份证国徽面">
            <el-upload
              :on-success="onUploadSuccessIdCard2"
              :on-remove="onUploadRemove"
              :multiple="false"
              :action="uploadUrl"
              :data="{ module: 'idCard2' }"
              :limit="1"
              list-type="picture-card"
            >
              <i class="el-icon-plus"></i>
            </el-upload>
          </el-form-item>
        </el-form>
        <!--其他信息-->
        <h6>其他信息</h6>
        <el-form label-width="120px">
          <el-form-item label="房产信息">
            <el-upload
              :on-success="onUploadSuccessHouse"
              :on-remove="onUploadRemove"
              :multiple="false"
              :action="uploadUrl"
              :data="{ module: 'house' }"
              list-type="picture-card"
            >
              <i class="el-icon-plus"></i>
            </el-upload>
          </el-form-item>
          <el-form-item label="车辆信息">
            <el-upload
              :on-success="onUploadSuccessCar"
              :on-remove="onUploadRemove"
              :multiple="false"
              :action="uploadUrl"
              :data="{ module: 'car' }"
              list-type="picture-card"
            >
              <i class="el-icon-plus"></i>
            </el-upload>
          </el-form-item>
        </el-form>

        <el-form label-width="120px">
          <el-form-item>
            <el-button
              type="primary"
              :disabled="submitBtnDisabled"
              @click="save"
            >
              提交
            </el-button>
          </el-form-item>
        </el-form>
      </div>
      <!--第二步-->
      <div v-if="active === 1">
        <div style="margin-top:40px;">
          <el-alert
            title="您的认证申请已成功提交,请耐心等待"
            type="warning"
            show-icon
            :closable="false"
          >
            我们将在2小时内完成审核,审核时间为周一至周五8:0020:00</el-alert>
        </div>
      </div>
      <!--第三步-->
      <div v-if="active === 2">
        <div style="margin-top:40px;">
          <el-alert
            v-if="borrowerStatus === 2"
            title="您的认证审批已通过"
            type="success"
            show-icon
            :closable="false"
          >
          </el-alert>

          <el-alert
            v-if="borrowerStatus === -1"
            title="您的认证审批未通过"
            type="error"
            show-icon
            :closable="false"
          >
          </el-alert>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    let BASE_API = process.env.BASE_API

    return {
      //为什么不设置为0?
      //因为只有当判断完成用户的认证状态才能确定在哪一步,如果写0的话如果用户状态为待审核由于ajax异步操作,会闪一下第一个列表
      active: null, //步骤
      borrowerStatus: null, //认证状态
      submitBtnDisabled: false, //提交按钮的修饰,防止表单重复提交,点击save然后不能提交
      //借款人信息
      borrower: {
        borrowerAttachList: [], //存储文件数据的基本信息
      },
      educationList: [], //学历列表
      industryList: [], //行业列表
      incomeList: [], //月收入列表
      returnSourceList: [], //还款来源列表
      contactsRelationList: [], //联系人关系
      uploadUrl: BASE_API + '/api/oss/file/upload', //文件上传地址
    }
  },

  methods: {
    //保存表单提交的信息
    save() {
      // debugger
      this.submitBtnDisabled = true
      this.$axios
        .$post('/api/core/borrower/auth/save', this.borrower)
        .then((response) => {
          this.active = 1
        })
    },
    //根据上传文件得到的结果,封装borrowerAttachList存储文件的基本信息(响应结果,文件参数)
    onUploadSuccessIdCard1(response, file) {
      this.onUploadSuccess(response, file, 'idCard1')
    },

    onUploadSuccessIdCard2(response, file) {
      this.onUploadSuccess(response, file, 'idCard2')
    },

    onUploadSuccessHouse(response, file) {
      this.onUploadSuccess(response, file, 'house')
    },

    onUploadSuccessCar(response, file) {
      this.onUploadSuccess(response, file, 'car')
    },

    onUploadSuccess(response, file, type) {
      // debugger
      if (response.code !== 0) {
        //上传失败,返回响应结果
        this.$message.error(response.message)
        return
      }
      // 上传成功,填充上传文件列表
      this.borrower.borrowerAttachList.push({
        imageName: file.name,
        imageUrl: response.data.url,
        imageType: type,
      })
      //console.log(this.borrower.borrowerAttachList)
    },

    //将oss系统删除文件(文件参数)file参数组装了上传的响应结果
    onUploadRemove(file, fileList) {
      console.log('file', file)
      console.log('fileList', fileList)
      //删除oss服务器上的内容
      //调用远程的删除接口
      this.$axios
        .$delete('/api/oss/file/remove?url=' + file.response.data.url)
        .then((response) => {
          // debugger
          console.log('远程删除文件成功')
          //从 this.borrower.borrowerAttachList列表中删除该文件
          //将过滤的结果回填到原来列表
          this.borrower.borrowerAttachList = this.borrower.borrowerAttachList.filter(
            function(item) {
              console.log('item', item)
              //两个地址相等则返回true,不删除
              return item.imageUrl != file.response.data.url
            }
          )
        })
    },

    //根据查询的数据字典初始化下拉列表
    initSelected() {
      //学历列表
      this.$axios
        .$get('/api/core/dict/findByDictCode/education')
        .then((response) => {
          this.educationList = response.data.dictList
        })

      //行业列表
      this.$axios
        .$get('/api/core/dict/findByDictCode/industry')
        .then((response) => {
          this.industryList = response.data.dictList
        })

      //收入列表
      this.$axios
        .$get('/api/core/dict/findByDictCode/income')
        .then((response) => {
          this.incomeList = response.data.dictList
        })

      //还款来源列表
      this.$axios
        .$get('/api/core/dict/findByDictCode/returnSource')
        .then((response) => {
          this.returnSourceList = response.data.dictList
        })

      //联系人关系列表
      this.$axios
        .$get('/api/core/dict/findByDictCode/relation')
        .then((response) => {
          this.contactsRelationList = response.data.dictList
        })
    },
    getUserInfo() {
      this.$axios
        .$get('/api/core/borrower/auth/getBorrowerStatus')
        .then((response) => {
          this.borrowerStatus = response.data.borrowerStatus

          if (this.borrowerStatus == 0) {
            //未认证,展示下拉列表
            this.active = 0
            this.initSelected()
          } else if (this.borrowerStatus == 1) {
            //审批中
            this.active = 1
          } else if (this.borrowerStatus == 2) {
            //审批通过
            this.active = 2
          } else if (this.borrowerStatus == -1) {
            //审批没通过
            this.active = 2
          }
        })
    },
  },

  created() {
    //更改为判断借款状态
    this.getUserInfo()
  },
}
</script>

5.后端代码逻辑

①前端调用的接口

  • 开发接口
    在这里插入图片描述
  • 调用的接口
    在这里插入图片描述

②后端复杂逻辑

  • 获取下拉列表时根据dict_code去查对应的子节点
    需要先查询到dict_code的id然后根据此id去查父id为此id的数据返回(调用之前写的根据父id查询的service)
  • 保存存款人信息时需要获取user_id绑定
    即需要用户先登录,此时可以从token中解析出user_id
  • 根据表单信息更新借款人表单时
    需要先根据user_id查询出user_info的基本信息,补充表单信息更新borrower表
  • 根据表单信息更新借款人附件表单时
    需要先查询借款人的id然后在附件表单中绑定借款人id
  • 提交表单后也需要更新user_info的借款人认证状态
  • 获取借款人认证状态
    可以从已登录的token中获取。然后根据id从borrower表中查询status,查询出数据则说明不是未认证返回status(1认证中2认证成功-1认证失败),查询不出数据则是未认证返回status(0未认证)

③后端创建的接受前端对象

package com.atguigu.srb.core.pojo.vo;

import com.atguigu.srb.core.pojo.entity.BorrowerAttach;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

@Data
@ApiModel(description="借款人认证信息")
public class BorrowerVO{

    @ApiModelProperty(value = "性别(1:男 0:女)")
    private Integer sex;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "学历")
    private Integer education;

    @ApiModelProperty(value = "是否结婚(1:是 0:否)")
    private Boolean marry;

    @ApiModelProperty(value = "行业")
    private Integer industry;

    @ApiModelProperty(value = "月收入")
    private Integer income;

    @ApiModelProperty(value = "还款来源")
    private Integer returnSource;

    @ApiModelProperty(value = "联系人名称")
    private String contactsName;

    @ApiModelProperty(value = "联系人手机")
    private String contactsMobile;

    @ApiModelProperty(value = "联系人关系")
    private Integer contactsRelation;

    @ApiModelProperty(value = "借款人附件资料")
    private List<BorrowerAttach> borrowerAttachList;
}

④获取数据字典业务

  • controller
package com.atguigu.srb.core.controller.api;


import com.atguigu.common.result.R;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.atguigu.srb.core.service.DictService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

@Api(tags = "数据字典")
@RestController
@RequestMapping("/api/core/dict")
@Slf4j
public class DictController {

    @Resource
    private DictService dictService;

    @ApiOperation("根据DictCode获取下级节点")
    @GetMapping("/findByDictCode/{dictCode}")
    public R findByDictCode(
            @ApiParam("节点编码")
            @PathVariable("dictCode") String dictCode){

        List<Dict> list =  dictService.findByDictCode(dictCode);
        return R.ok().data("dictList",list);

    }
}

  • service(前三种方法是admin管理系统调用的Dict方法)
package com.atguigu.srb.core.service;

import com.atguigu.srb.core.pojo.dto.ExcelDictDTO;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.baomidou.mybatisplus.extension.service.IService;

import java.io.InputStream;
import java.util.List;

/**
 * <p>
 * 数据字典 服务类
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
public interface DictService extends IService<Dict> {


    void importData(InputStream inputStream);

    List<ExcelDictDTO> listDictData();

    List<Dict> listByParentId(Long parentId);

    /**
     * @param dictCode:
     * @return List<Dict>
     * @author Likejin
     * @description 根据dictCode编码查询其下级节点
     * @date 2023/4/15 20:00
     */

    List<Dict> findByDictCode(String dictCode);
}

com.atguigu.srb.core.service.impl.DictServiceImpl类下加入方法

    /**
     * @param dictCode:
     * @return List<Dict>
     * @author Likejin
     * @description 根据dictCode编码查询其下级节点
     * @date 2023/4/15 20:00
     */
    @Override
    public List<Dict> findByDictCode(String dictCode) {
        QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
        dictQueryWrapper.eq("dict_code",dictCode);
        Dict dict = baseMapper.selectOne(dictQueryWrapper);
        //拿到父dict的id,然后根据该id去查父id等于这个id的list<Dict>
        return this.listByParentId(dict.getId());
    }

⑤借款人业务(获取认证状态)(保存借款人信息)

  • controller
package com.atguigu.srb.core.controller.api;

import com.atguigu.common.result.R;
import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.core.pojo.vo.BorrowerVO;
import com.atguigu.srb.core.service.BorrowerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Api(tags = "借款人")
@RestController
@RequestMapping("/api/core/borrower")
@Slf4j
public class BorrowerController {

    @Resource
    private BorrowerService borrowerService;

    @ApiOperation("保存借款人信息")
    @PostMapping("/auth/save")
    public R save(@RequestBody BorrowerVO borrowerVO, HttpServletRequest request) {
        //获取已经登录人的id
        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);

        //存储表单信息
        borrowerService.saveBorrowerVOByUserId(borrowerVO, userId);
        return R.ok().message("信息提交成功");
    }

    @ApiOperation("获取借款人认证状态")
    @GetMapping("/auth/getBorrowerStatus")
    public R getBorrowerStatus(HttpServletRequest httpServletRequest){
        String token = httpServletRequest.getHeader("token");
        Long userId = JwtUtils.getUserId(token);
        Integer status = borrowerService.getStatusByUserId(userId);
        return R.ok().data("borrowerStatus",status);


    }
}
  • service
package com.atguigu.srb.core.service;

import com.atguigu.srb.core.pojo.entity.Borrower;
import com.atguigu.srb.core.pojo.vo.BorrowerVO;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * <p>
 * 借款人 服务类
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
public interface BorrowerService extends IService<Borrower> {


    void saveBorrowerVOByUserId(BorrowerVO borrowerVO, Long userId);


    Integer getStatusByUserId(Long userId);
}

package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.core.enums.BorrowerStatusEnum;
import com.atguigu.srb.core.mapper.BorrowerAttachMapper;
import com.atguigu.srb.core.mapper.UserInfoMapper;
import com.atguigu.srb.core.pojo.entity.Borrower;
import com.atguigu.srb.core.mapper.BorrowerMapper;
import com.atguigu.srb.core.pojo.entity.BorrowerAttach;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.vo.BorrowerVO;
import com.atguigu.srb.core.service.BorrowerService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 借款人 服务实现类
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
@Service
public class BorrowerServiceImpl extends ServiceImpl<BorrowerMapper, Borrower> implements BorrowerService {


    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private BorrowerAttachMapper borrowerAttachMapper;
    /**
     * @param borrowerVO:
     * @param userId:
     * @return void
     * @author Likejin
     * @description 根据前端传输对象保存数据到数据库
     * @date 2023/4/15 20:15
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBorrowerVOByUserId(BorrowerVO borrowerVO, Long userId) {


        //获取用户基本信息
        UserInfo userInfo = userInfoMapper.selectById(userId);
        //拷贝信息到borrower
        //保存借款人信息(根据id查询用户基本信息,然后根据表单信息更新borrower表)
        Borrower borrower = new Borrower();
        BeanUtils.copyProperties(borrowerVO,borrower);
        borrower.setUserId(userId);
        borrower.setName(userInfo.getName());
        borrower.setIdCard(userInfo.getIdCard());
        borrower.setMobile(userInfo.getMobile());
        borrower.setStatus(BorrowerStatusEnum.AUTH_RUN.getStatus());
        baseMapper.insert(borrower);

        //保存附件信息到borrow——attach表
        List<BorrowerAttach> borrowerAttachList = borrowerVO.getBorrowerAttachList();
        borrowerAttachList.forEach(borrowerAttach -> {
            borrowerAttach.setBorrowerId(borrower.getId());
            borrowerAttachMapper.insert(borrowerAttach);
        });

        //更新user_info的借款人认证状态
        userInfo.setBorrowAuthStatus(BorrowerStatusEnum.AUTH_RUN.getStatus());
        userInfoMapper.updateById(userInfo);

    }

    /**
     * @param userId:
     * @return Integer
     * @author Likejin
     * @description 借款人二次进入认证页面根据token获取认证状态
     * @date 2023/4/15 20:41
     */

    @Override
    public Integer getStatusByUserId(Long userId) {

        QueryWrapper<Borrower> borrowerQueryWrapper = new QueryWrapper<>();
        borrowerQueryWrapper.select("status").eq("user_id",userId);
        //selectObjs一般用于查询一个字段,list存的是status
        List<Object> objects = baseMapper.selectObjs(borrowerQueryWrapper);
        if(objects.size()==0){
            //一条记录没取出来,说明没有提交额度信息,需要填写表单
            return BorrowerStatusEnum.NO_AUTH.getStatus();
        }
        //取出来一条,说明已经提交了额度信息,判断此时状态
        Integer status = (Integer) objects.get(0);
        return status;
    }
}

6.用户个人信息后管理员审批流程

①在后台管理系统添加借款人列表

在这里插入图片描述

②后台管理系统的借款人列表展示

在这里插入图片描述

③单击审批进入审批页的页面展示

在这里插入图片描述

④前后端联调

  • 前端需要增加路由设置
  • 需要增加借款人表单列表
  • 需要增加额度审批表单

⑤前后端联调

  • 后端需要获取借款人分页列表
  • 获取借款人表单信息

7.前端代码逻辑

①前端对应表单对象

  • 展示借款人列表表单
    在这里插入图片描述
  • 展示审批表单
    在这里插入图片描述

②前端对应路由

  • 前端增加借款管理路由(内部)
    在这里插入图片描述
  • 前端调用后端路由
    在这里插入图片描述

③前端具体代码

  • 增加内部导航路由
    srb-admin\src\router\index.js
{
    path: '/core/borrower',
    component: Layout,
    name: 'coreBorrower',
    meta: { title: '借款管理', icon: 'el-icon-s-unfold' },
    alwaysShow: true,
    children: [
      {
        path: 'list',
        name: 'coreBorrowerList',
        component: () => import('@/views/core/borrower/list'),
        meta: { title: '借款人列表' },
      },
      {
        path: 'detail/:id',
        name: 'coreBorrowerDetail',
        component: () => import('@/views/core/borrower/detail'),
        meta: { title: '借款人详情' },
        hidden: true,
      },
    ],
  },
  • 增加调用后端api的接口
    srb-admin\src\api\core\borrower.js
import request from '@/utils/request'

export default {
  //根据分页信息和关键字查询借款人信息
  getPageList(page, limit, keyword) {
    return request({
      url: `/admin/core/borrower/list/${page}/${limit}`,
      method: 'get',
      params: { keyword },
    })
  },
  //根据id展示借款人认证信息
  show(id) {
    return request({
      url: `/admin/core/borrower/show/${id}`,
      method: 'get',
    })
  },
}

  • 增加页面组件(借款人信息)
    srb-admin\src\views\core\borrower\list.vue
<template>
  <div class="app-container">
    <!--查询表单-->
    <el-form :inline="true">
      <el-form-item label="关键字">
        <el-input v-model="keyword" placeholder="姓名/手机/身份证" />
      </el-form-item>
      <el-button type="primary" icon="el-icon-search" @click="fetchData()">
        查询
      </el-button>
      <el-button type="default" @click="resetData()">清空</el-button>
    </el-form>

    <!-- 列表 -->
    <el-table :data="list" stripe>
      <el-table-column label="序号" width="70" align="center">
        <template slot-scope="scope">
          {{ (page - 1) * limit + scope.$index + 1 }}
        </template>
      </el-table-column>

      <el-table-column prop="name" label="姓名" />
      <el-table-column prop="mobile" label="手机" />
      <el-table-column prop="idCard" label="身份证号" width="200" />
      <el-table-column label="性别" width="80">
        <template slot-scope="scope">
          {{ scope.row.sex === 1 ? '男' : '女' }}
        </template>
      </el-table-column>

      <el-table-column prop="age" label="年龄" width="80" />

      <el-table-column label="是否结婚" width="120">
        <template slot-scope="scope">
          {{ scope.row.marry ? '是' : '否' }}
        </template>
      </el-table-column>

      <el-table-column label="状态" width="100">
        <template slot-scope="scope">
          <el-tag v-if="scope.row.status === 0" type="info" size="mini">
            未认证
          </el-tag>
          <el-tag v-if="scope.row.status === 1" type="warning" size="mini">
            认证中
          </el-tag>
          <el-tag v-if="scope.row.status === 2" type="success" size="mini">
            认证通过
          </el-tag>
          <el-tag v-if="scope.row.status === -1" type="danger" size="mini">
            认证失败
          </el-tag>
        </template>
      </el-table-column>

      <el-table-column prop="createTime" label="申请时间" width="160" />

      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <router-link :to="'/core/borrower/detail/' + scope.row.id">
            <el-button v-if="scope.row.status === 1" type="warning" size="mini">
              审批
            </el-button>
            <el-button v-else type="primary" size="mini">查看</el-button>
          </router-link>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页组件 -->
    <el-pagination
      :current-page="page"
      :total="total"
      :page-size="limit"
      :page-sizes="[2, 10, 20]"
      style="padding: 30px 0"
      layout="total, sizes, prev, pager, next, jumper"
      @size-change="changePageSize"
      @current-change="changeCurrentPage"
    />
  </div>
</template>

<script>
import borrowerApi from '@/api/core/borrower'

export default {
  data() {
    return {
      list: null, // banner列表
      total: 0, // 数据库中的总记录数
      page: 1, // 默认页码
      limit: 10, // 每页记录数
      keyword: '', // 查询表单对象
    }
  },

  // 生命周期函数:内存准备完毕,页面尚未渲染
  created() {
    this.fetchData()
  },

  methods: {
    // 加载banner列表数据
    fetchData() {
      borrowerApi
        .getPageList(this.page, this.limit, this.keyword)
        .then((response) => {
          this.list = response.data.pageModel.records
          this.total = response.data.pageModel.total
        })
    },

    // 每页记录数改变,size:回调参数,表示当前选中的“每页条数”
    changePageSize(size) {
      this.limit = size
      this.fetchData()
    },

    // 改变页码,page:回调参数,表示当前选中的“页码”
    changeCurrentPage(page) {
      this.page = page
      this.fetchData()
    },

    // 重置表单
    resetData() {
      this.keyword = ''
      this.fetchData()
    },
  },
}
</script>

  • 增加页面组件(审批单信息)
    srb-admin\src\views\core\borrower\detail.vue
<template>
  <div class="app-container">
    <el-form label-width="100px" class="form-table">
      <el-row>
        <el-col :span="6">
          <el-form-item label="状态">
            {{ borrower.status }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="创建时间">
            {{ borrower.createTime }}
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="6">
          <el-form-item label="姓名">
            {{ borrower.name }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="性别">
            {{ borrower.sex }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="年龄">
            {{ borrower.age }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="手机">
            {{ borrower.mobile }}
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="6">
          <el-form-item label="学历">
            {{ borrower.education }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="是否结婚">
            {{ borrower.marry }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="行业">
            {{ borrower.industry }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="还款来源">
            {{ borrower.returnSource }}
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="6">
          <el-form-item label="身份证号">
            {{ borrower.idCard }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="联系人名称">
            {{ borrower.contactsName }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="联系人手机">
            {{ borrower.contactsMobile }}
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="联系人关系">
            {{ borrower.contactsRelation }}
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-form-item label="身份证正面">
            <span v-for="item in borrower.borrowerAttachVOList" :key="item.id">
              <el-image
                v-if="item.imageType == 'idCard1'"
                style="width: 150px"
                :src="item.imageUrl"
                :preview-src-list="[item.imageUrl]"
              />
            </span>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-form-item label="身份证反面">
            <span v-for="item in borrower.borrowerAttachVOList" :key="item.id">
              <el-image
                v-if="item.imageType == 'idCard2'"
                style="width: 150px"
                :src="item.imageUrl"
                :preview-src-list="[item.imageUrl]"
              />
            </span>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-form-item label="房产信息">
            <span v-for="item in borrower.borrowerAttachVOList" :key="item.id">
              <el-image
                v-if="item.imageType == 'house'"
                style="width: 150px"
                :src="item.imageUrl"
                :preview-src-list="[item.imageUrl]"
              />
            </span>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-form-item label="车辆信息">
            <span v-for="item in borrower.borrowerAttachVOList" :key="item.id">
              <el-image
                v-if="item.imageType == 'car'"
                style="width: 150px"
                :src="item.imageUrl"
                :preview-src-list="[item.imageUrl]"
              />
            </span>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row style="text-align: center">
        <el-button @click="back">返回</el-button>
      </el-row>
    </el-form>
  </div>
</template>

<script>
// 引入组件
import borrowerApi from '@/api/core/borrower'

export default {
  data() {
    return {
      borrower: {}, //借款用户信息
      saveBtnDisabled: false, //防止重复提交
      approvalForm: {
        //审批表单
        borrowerId: 0,
        status: 2,
        content: '',
        infoIntegral: 30,
        isIdCardOk: false,
        isHouseOk: false,
        isCarOk: false,
      },
    }
  },

  //页面一加载就调用
  created() {
    //如果有id,就查询记录
    if (this.$route.params.id) {
      this.fetchDataById()
    }
  },

  methods: {
    // 根据id查询记录
    fetchDataById() {
      borrowerApi.show(this.$route.params.id).then((response) => {
        this.borrower = response.data.borrowerDetailVO
      })
    },

    //从审批页回到列表页
    back() {
      this.$router.push({ path: '/core/borrower/list' })
    },
  },
}
</script>

④前端代码逻辑难点

  • 展示图片信息(利用后端返回的url)
    在这里插入图片描述

8.后端代码逻辑

①后端开发接口

在这里插入图片描述

②封装前端的对象

  • 借款人表单返回borrower对象即可
  • 审核表单vo
package com.atguigu.srb.core.pojo.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.List;

@Data
@ApiModel(description="借款人信息详情")
public class BorrowerDetailVO {

    @ApiModelProperty(value = "用户id")
    private Long userId;

    @ApiModelProperty(value = "姓名")
    private String name;

    @ApiModelProperty(value = "身份证号")
    private String idCard;

    @ApiModelProperty(value = "手机")
    private String mobile;

    @ApiModelProperty(value = "性别")
    private String sex;

    @ApiModelProperty(value = "年龄")
    private Integer age;

    @ApiModelProperty(value = "学历")
    private String education;

    @ApiModelProperty(value = "是否结婚")
    private String marry;

    @ApiModelProperty(value = "行业")
    private String industry;

    @ApiModelProperty(value = "月收入")
    private String income;

    @ApiModelProperty(value = "还款来源")
    private String returnSource;

    @ApiModelProperty(value = "联系人名称")
    private String contactsName;

    @ApiModelProperty(value = "联系人手机")
    private String contactsMobile;

    @ApiModelProperty(value = "联系人关系")
    private String contactsRelation;

    @ApiModelProperty(value = "审核状态")
    private String status;

    @ApiModelProperty(value = "创建时间")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "借款人附件资料")
    private List<BorrowerAttachVO> borrowerAttachVOList;
}
  • 审核表单的图片数据vo
package com.atguigu.srb.core.pojo.vo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(value="借款人附件资料")
public class BorrowerAttachVO {

    @ApiModelProperty(value = "图片类型(idCard1:身份证正面,idCard2:身份证反面,house:房产证,car:车)")
    private String imageType;

    @ApiModelProperty(value = "图片路径")
    private String imageUrl;
}

③开发接口

  • controller
package com.atguigu.srb.core.controller.admin;

import com.atguigu.common.result.R;
import com.atguigu.srb.core.pojo.entity.Borrower;
import com.atguigu.srb.core.pojo.vo.BorrowerDetailVO;
import com.atguigu.srb.core.service.BorrowerService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@Api(tags = "借款人管理")
@RestController
@RequestMapping("/admin/core/borrower")
@Slf4j
public class AdminBorrowerController {

    @Resource
    private BorrowerService borrowerService;

    @ApiOperation("获取借款人分页列表")
    @GetMapping("/list/{page}/{limit}")
    public R listPage(
            @ApiParam(value = "当前页码", required = true)
            @PathVariable Long page,

            @ApiParam(value = "每页记录数", required = true)
            @PathVariable Long limit,

            @ApiParam(value = "查询关键字", required = false)
            @RequestParam String keyword) {
        //这里的@RequestParam其实是可以省略的,但是在目前的swagger版本中(2.9.2)不能省略,
        //否则默认将没有注解的参数解析为body中的传递的数据

        Page<Borrower> pageParam = new Page<>(page, limit);
        IPage<Borrower> pageModel = borrowerService.listPage(pageParam, keyword);
        return R.ok().data("pageModel", pageModel);
    }

    @ApiOperation("获取借款人信息")
    @GetMapping("/show/{id}")
    public R show(
            @ApiParam(value = "借款人id", required = true)
            @PathVariable Long id) {
        //封装vo信息
        BorrowerDetailVO borrowerDetailVO = borrowerService.getBorrowerDetailVOById(id);
        return R.ok().data("borrowerDetailVO", borrowerDetailVO);
    }
}
  • 展示借款人列表查询分页信息service
    com.atguigu.srb.core.service.BorrowerService
IPage<Borrower> listPage(Page<Borrower> pageParam, String keyword);
    /**
     * @param pageParam:
     * @param keyword:
     * @return IPage<Borrower>
     * @author Likejin
     * @description 根据页码和一页展示的数量去查询。或者包含查询条件关键字(姓名,手机号码,身份证)
     * @date 2023/4/16 9:52
     */

    @Override
    public IPage<Borrower> listPage(Page<Borrower> pageParam, String keyword) {
        if(StringUtils.isBlank(keyword)){
            return baseMapper.selectPage(pageParam,null);
        }
        QueryWrapper<Borrower> borrowerQueryWrapper = new QueryWrapper<>();
        borrowerQueryWrapper
                .or().like("id_card", keyword)
                .or().like("mobile", keyword)
                .orderByDesc("id")
                .orderByDesc("id");
        return baseMapper.selectPage(pageParam,borrowerQueryWrapper);
    }
  • 封装审批表单service
    com.atguigu.srb.core.service.BorrowerService
BorrowerDetailVO getBorrowerDetailVOById(Long id);
/**
     * @param id:
     * @return BorrowerDetailVO
     * @author Likejin
     * @description 根据id封装前端所需对象BorrowerDetailVO
     * @date 2023/4/16 10:17
     */
    @Override
    public BorrowerDetailVO getBorrowerDetailVOById(Long id) {
        //获取借款人信息
        Borrower borrower = baseMapper.selectById(id);
        BorrowerDetailVO borrowerDetailVO = new BorrowerDetailVO();
        //对应字段的填充
        BeanUtils.copyProperties(borrower,borrowerDetailVO);

        //婚否
        borrowerDetailVO.setMarry(borrower.getMarry()?"是":"否");
        //性别
        borrowerDetailVO.setSex(borrower.getSex()==1?"男":"女");

        //计算下拉列表选中内容(borrower中存储数值了,需要通过数值获取相应的字符)
        //根据dict_code和value获取到相应的文本
        String education = dictService.getNameByParentDictCodeAndValue("education", borrower.getEducation());
        String industry = dictService.getNameByParentDictCodeAndValue("industry", borrower.getIndustry());
        String income = dictService.getNameByParentDictCodeAndValue("income", borrower.getIncome());
        String returnSource = dictService.getNameByParentDictCodeAndValue("returnSource", borrower.getReturnSource());
        String contactsRelation = dictService.getNameByParentDictCodeAndValue("relation", borrower.getContactsRelation());

        //设置下拉列表选中内容
        borrowerDetailVO.setEducation(education);
        borrowerDetailVO.setIndustry(industry);
        borrowerDetailVO.setIncome(income);
        borrowerDetailVO.setReturnSource(returnSource);
        borrowerDetailVO.setContactsRelation(contactsRelation);

        //审批状态,设置审批状态(通过status来获取文本值)
        String status = BorrowerStatusEnum.getMsgByStatus(borrower.getStatus());
        borrowerDetailVO.setStatus(status);

        //获取附件VO列表(个根据borrower_id查询所有的borrower的附件表并且封装为list)
        List<BorrowerAttachVO> borrowerAttachVOList =  borrowerAttachService.selectBorrowerAttachVOList(id);
        borrowerDetailVO.setBorrowerAttachVOList(borrowerAttachVOList);

        return borrowerDetailVO;

    }
  • 封装审批表单BorrowerService调用DictService
    根据borrower信息的编码获取对应的字符串(根据value获得name展示在前端对应的行)
    在这里插入图片描述
    com.atguigu.srb.core.service.DictService
String getNameByParentDictCodeAndValue(String dictCode, Integer value);
 /**
     * @param dictCode:
     * @param value:
     * @return String
     * @author Likejin
     * @description 根据父dict_code和value来获取具体文本值
     * @date 2023/4/16 10:23
     */
    @Override
    public String getNameByParentDictCodeAndValue(String dictCode, Integer value) {
        //根据父dict_code获取父id
        QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
        dictQueryWrapper.eq("dict_code",dictCode);
        Dict parentDict = baseMapper.selectOne(dictQueryWrapper);
        if(parentDict == null){
            return "";
        }
        Long id = parentDict.getId();
        //根据获取的父id和value定位唯一一条子数据获得其name
        dictQueryWrapper = new QueryWrapper<>();
        dictQueryWrapper.eq("parent_id",id)
                .eq("value",value);
        Dict dict = baseMapper.selectOne(dictQueryWrapper);
        if(dict == null){
            return "";
        }
        String name = dict.getName();
        return name;
    }
  • 封装审批表单BorrowerService调用BorrowerAttachService
    需要查出其下borrower对象下面的所有BorrowerAttach
    com.atguigu.srb.core.service.BorrowerAttachService
 List<BorrowerAttachVO> selectBorrowerAttachVOList(Long id);
 /**
     * @param id:
     * @return List<BorrowerAttachVO>
     * @author Likejin
     * @description 根据borrower的id获取所有的附件信息封装为列表
     * @date 2023/4/16 10:36
     */

    @Override
    public List<BorrowerAttachVO> selectBorrowerAttachVOList(Long id) {

        QueryWrapper<BorrowerAttach> borrowerAttachQueryWrapper = new QueryWrapper<>();
        borrowerAttachQueryWrapper.eq("borrower_id",id);
        List<BorrowerAttach> borrowerAttaches = baseMapper.selectList(borrowerAttachQueryWrapper);

        ArrayList<BorrowerAttachVO> borrowerAttachVOList = new ArrayList<>();
        //创建一个BorrowerAttachVO的列表
        borrowerAttaches.forEach(borrowerAttach -> {
            BorrowerAttachVO borrowerAttachVO = new BorrowerAttachVO();
            borrowerAttachVO.setImageType(borrowerAttach.getImageType());
            borrowerAttachVO.setImageUrl(borrowerAttach.getImageUrl());

            borrowerAttachVOList.add(borrowerAttachVO);
        });
        return borrowerAttachVOList;
    }

④后端代码逻辑难点

  • 获取借款人列表
    关键字可传可不传,不传就是null,传了就是模糊查询
  • 获取审批表单数据
    根据前端传入的borrower_id来获取表单数据信息。
    根据borrower_id查询borrower数据表获取基本信息。封装BorrowerDetailVO
    根据borrower的信息编码查dict数据表获取编码对应字符串。封装BorrowerDetailVO
    根据borrwer的id查询所有的borrower的附件。封装BorrowerDetailVO的borrowerAttachVOList<BorrowerAttachVO>

9.展示用户个人信息后管理员修改状态更改积分流程

①上述流程已经展示了用户个人信息

②管理员评估积分并审核

在这里插入图片描述

③审核通过

  • 管理系统
    会员获得积分
    在这里插入图片描述
    借款人状态认证通过
    在这里插入图片描述
    前端借款人认证状态为等待认证结果
    在这里插入图片描述

10.数据库涉及表

①用户积分表(展示用户积分修改明细)

user_intergral
在这里插入图片描述

③用户积分表和用户表和借款人表关联

  • 用户积分表user_intergral的明细加起来则为用户表user_info的总积分
  • 用户表通过user_id和借款人borrower表想关联
  • 插入用户积分明细同时用户表和借款人表都会更新状态status为认证成功

11.前端代码逻辑

①数据对象

在这里插入图片描述

②调用接口

在这里插入图片描述

③代码

  • 调用接口
    srb-admin\src\api\core\borrower.js
//封装审核表单对象提交
  approval(borrowerApproval) {
    return request({
      url: '/admin/core/borrower/approval',
      method: 'post',
      data: borrowerApproval,
    })
  },
  • 更改表单
    srb-admin\src\views\core\borrower\detail.vue
 <!--审批模板-->
    <el-form label-width="170px" v-if="borrower.status === '认证中'">
      <el-form-item label="是否通过">
        <el-radio-group v-model="approvalForm.status">
          <el-radio :label="2">通过</el-radio>
          <el-radio :label="-1">不通过</el-radio>
        </el-radio-group>
      </el-form-item>

      <el-form-item v-if="approvalForm.status == 2" label="基本信息积分">
        <el-input v-model="approvalForm.infoIntegral" style="width: 140px" />
        <span style="color: indianred">(可获取30100积分)</span>
      </el-form-item>

      <el-form-item v-if="approvalForm.status == 2" label="身份证信息是否正确">
        <el-radio-group v-model="approvalForm.isIdCardOk">
          <el-radio :label="true"></el-radio>
          <el-radio :label="false"></el-radio>
        </el-radio-group>
        <span style="color: indianred">(可获得积分30积分)</span>
      </el-form-item>

      <el-form-item v-if="approvalForm.status == 2" label="车辆信息是否正确">
        <el-radio-group v-model="approvalForm.isCarOk">
          <el-radio :label="true"></el-radio>
          <el-radio :label="false"></el-radio>
        </el-radio-group>
        <span style="color: indianred">(可获得积分60积分)</span>
      </el-form-item>

      <el-form-item v-if="approvalForm.status == 2" label="房产信息是否正确">
        <el-radio-group v-model="approvalForm.isHouseOk">
          <el-radio :label="true"></el-radio>
          <el-radio :label="false"></el-radio>
        </el-radio-group>
        <span style="color: indianred">(可获得积分100积分)</span>
      </el-form-item>

      <el-row style="text-align: center">
        <el-button type="primary" @click="approvalSubmit()">确定</el-button>
      </el-row>
    </el-form>

methods方法中添加


    //表单审批积分提交和状态修改
    approvalSubmit() {
      this.saveBtnDisabled = true
      //封装一个borrower_id(表单中没有)
      this.approvalForm.borrowerId = this.$route.params.id
      borrowerApi.approval(this.approvalForm).then((response) => {
        this.$message.success(response.message)
        this.$router.push({ path: '/core/borrower/list' })
      })
    },

④前端代码难点

  • 需要更新user_info和borrower和user_integral表故需要borrow的id
    可以从this.$route.params.id获取id,因为是从外面表单点进来故保存了id

12.后端代码逻辑

①对应前端数据对象

  • 注意id表单没有前端需要获得
    在这里插入图片描述

②接口地址

在这里插入图片描述

③代码实现

  • controller
    com.atguigu.srb.core.controller.admin.AdminBorrowerController
 @ApiOperation("借款额度审批")
    @PostMapping("/approval")
    public R approval(@RequestBody BorrowerApprovalVO borrowerApprovalVO) {
        //额度审批的目标:
        // 在user_integral表添加积分明细。在user_info添加总积分。
        // 修改borrower表的借款申请审核状态。修改user_info的借款申请审核状态


        //得到审批结果表单(获取对应积分)
        borrowerService.approval(borrowerApprovalVO);
        return R.ok().message("审批完成");
    }
  • service
    com.atguigu.srb.core.service.BorrowerService
void approval(BorrowerApprovalVO borrowerApprovalVO);
    /**
     * @param borrowerApprovalVO:
     * @return void
     * @author Likejin 管理员根据提交的Vo对象更改状态并且保存积分明细
     * @description
     * @date 2023/4/16 12:57
     */

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void approval(BorrowerApprovalVO borrowerApprovalVO) {
        //注意:user_integral表存储积分明细,每一次积分变动的信息(基本信息 获得积分,身份证 获得的积分)

        //根据提交对象拿到借款人的id
        Long borrowerId = borrowerApprovalVO.getBorrowerId();

        //获取借款人对象
        Borrower borrower = baseMapper.selectById(borrowerId);

        //设置审核状态
        //前端传来的通过与不通过的status值(2,-1)
        borrower.setStatus(borrowerApprovalVO.getStatus());
        baseMapper.updateById(borrower);

        //获取用户id
        Long userId = borrower.getUserId();

        //获取用户对象(以便更改user_info的总积分integral)
        UserInfo userInfo = userInfoMapper.selectById(userId);
        //获取原始积分
        Integer integral = userInfo.getIntegral();

        //计算基本信息积分(更新user_integral的表)
        UserIntegral userIntegral = new UserIntegral();
        userIntegral.setUserId(userId);
        userIntegral.setIntegral(borrowerApprovalVO.getInfoIntegral());
        userIntegral.setContent("借款人基本信息");

        userIntegralMapper.insert(userIntegral);

        //要更新的积分
        int currentIntegral = integral + borrowerApprovalVO.getInfoIntegral();

        //身份证积分
        if(borrowerApprovalVO.getIsCarOk()){
            //计算基本信息积分(更新user_integral的表)
            userIntegral = new UserIntegral();
            userIntegral.setUserId(userId);
            userIntegral.setIntegral(IntegralEnum.BORROWER_IDCARD.getIntegral());
            userIntegral.setContent(IntegralEnum.BORROWER_IDCARD.getMsg());
            userIntegralMapper.insert(userIntegral);

            //加上身份证积分
            currentIntegral += IntegralEnum.BORROWER_IDCARD.getIntegral();
        }

        //房产积分
        if(borrowerApprovalVO.getIsHouseOk()) {
            userIntegral = new UserIntegral();
            userIntegral.setUserId(userId);
            userIntegral.setIntegral(IntegralEnum.BORROWER_HOUSE.getIntegral());
            userIntegral.setContent(IntegralEnum.BORROWER_HOUSE.getMsg());
            userIntegralMapper.insert(userIntegral);


            //加上房产积分
            currentIntegral += IntegralEnum.BORROWER_HOUSE.getIntegral();
        }

        //车辆信息
        if(borrowerApprovalVO.getIsCarOk()) {
            userIntegral = new UserIntegral();
            userIntegral.setUserId(userId);
            userIntegral.setIntegral(IntegralEnum.BORROWER_CAR.getIntegral());
            userIntegral.setContent(IntegralEnum.BORROWER_CAR.getMsg());
            userIntegralMapper.insert(userIntegral);


            //加上车辆积分
            currentIntegral += IntegralEnum.BORROWER_CAR.getIntegral();
        }

        //将总用户积分加起来存到user_info表中
        //修改用户总结分
        userInfo.setIntegral(currentIntegral);

        //修改用户审核状态
        userInfo.setBorrowAuthStatus(borrowerApprovalVO.getStatus());

        //更新user_info
        userInfoMapper.updateById(userInfo);
    }

④后端逻辑难点

  • 后端目标
    在user_integral表添加积分明细。在user_info添加总积分。
    修改borrower表的借款申请审核状态。修改user_info的借款申请审核状态
  • 只有borrower_id如何获得user_info和user_integral
    先从borrower表中查出对应的user_id,并更新borrower表状态,再利用user_id更改user_info的状态并且增加积分明细到user_integral,最后根据积分明细更改总积分到user_info

未更新

未更新

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值