【金融项目】尚融宝项目(十)

19、申请借款额度

19.1、需求介绍

19.1.1、借款人申请额度

1、需求描述

【金融项目】尚融宝项目(十)_第1张图片

平台管理员根据借款人个人信息设置积分,通过积分规则借款人可以获取额度。

2、相关数据库表

【金融项目】尚融宝项目(十)_第2张图片

19.1.2、具体步骤

step1:用户在个人中心点击 “立即借款” (http://localhost:3000/user/borrower)

step2:展示借款人信息认证页面

【金融项目】尚融宝项目(十)_第3张图片

step3:借款人填写信息并提交

step4:展示等待审核页面

【金融项目】尚融宝项目(十)_第4张图片

step5:平台审核

step6:显示审批结果

【金融项目】尚融宝项目(十)_第5张图片

【金融项目】尚融宝项目(十)_第6张图片

19.2、借款人信息表单

19.2.1、步骤导航

1、参考

Steps 步骤条:https://element.eleme.io/#/zh-CN/component/steps

Alert 警告:

2、页面模板

这个页面比较复杂,因此我们一步一步创建,熟悉页面结构

创建 pages/user/borrower.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>
        <h6>联系人信息h6>
        <h6>身份认证信息h6>
        <h6>其他信息h6>
        <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:00至20: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 {
      active: 0, //步骤
      borrowerStatus: null,
      submitBtnDisabled: false,
      //借款人信息
      borrower: {
        borrowerAttachList: [],
      },
      educationList: [], //学历列表
      industryList: [], //行业列表
      incomeList: [], //月收入列表
      returnSourceList: [], //还款来源列表
      contactsRelationList: [], //联系人关系
      uploadUrl: BASE_API + '/api/oss/file/upload', //文件上传地址
    }
  },
  methods: {
    save() {
      this.submitBtnDisabled = true
      this.active = 1
    },
  },
}
script>

19.2.2、借款人信息页面

1、个人基本信息

<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>

2、联系人信息

<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>

3、身份认证信息

<h6>身份认证信息h6>
<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>

4、其他信息

<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>

5、文件上传

pages/user/borrower.vue

定义methods:

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,
  })
},
onUploadRemove(file, fileList) {
  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.filter(
        function(item) {
          console.log('item', item)
          return item.imageUrl != file.response.data.url
        }
      )
    })
},

19.3、表单数据展示

19.3.1、根据编码获取数据字典

1、controller

sevice-core中添加接口方法

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

@Api(tags = "数据字典")
@RestController
@RequestMapping("/api/core/dict")
@Slf4j
public class DictController {
    @Resource
    private DictService dictService;
    @ApiOperation("根据dictCode获取下级节点")
    @GetMapping("/findByDictCode/{dictCode}")
    public R findByDictCode(
            @ApiParam(value = "节点编码", required = true)
            @PathVariable String dictCode) {
        List<Dict> list = dictService.findByDictCode(dictCode);
        return R.ok().data("dictList", list);
    }
}

2、service

接口:DictService

List<Dict> findByDictCode(String dictCode);

实现:DictServiceImpl

@Override
public List<Dict> findByDictCode(String dictCode) {
    QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
    dictQueryWrapper.eq("dict_code", dictCode);
    Dict dict = baseMapper.selectOne(dictQueryWrapper);
    return this.listByParentId(dict.getId());
}

19.3.2、前端展示借款人信息

展示下拉列表

pages/user/borrower.vue中调用接口

定义methods:

   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
        })
    },

页面加载时调用

  created() {
    this.initSelected()
  },

19.4、表单数据提交

19.4.1、后端开发

1、定义VO对象

service-core微服务,创建BorrowerVO

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

@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;
}

2、定义枚举

BorrowerStatusEnum

数据库设计中对应认证状态status (0:未认证,1:认证中, 2:认证通过, -1:认证失败)

3、controller

service-core中在BorrowerController中定义接口方法

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

@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) {
        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);
        borrowerService.saveBorrowerVOByUserId(borrowerVO, userId);
        return R.ok().message("信息提交成功");
    }
}

4、service

接口:BorrowerService

void saveBorrowerVOByUserId(BorrowerVO borrowerVO, Long userId);

实现:BorrowerServiceImpl

@Resource
private BorrowerAttachMapper borrowerAttachMapper;
@Resource
private UserInfoMapper userInfoMapper;

@Transactional(rollbackFor = Exception.class)
@Override
public void saveBorrowerVOByUserId(BorrowerVO borrowerVO, Long userId) {
    UserInfo userInfo = userInfoMapper.selectById(userId);
    //保存借款人信息
    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);
    //保存附件
    List<BorrowerAttach> borrowerAttachList = borrowerVO.getBorrowerAttachList();
    borrowerAttachList.forEach(borrowerAttach -> {
        borrowerAttach.setBorrowerId(borrower.getId());
        borrowerAttachMapper.insert(borrowerAttach);
    });
    
    //更新会员状态,更新为认证中
    userInfo.setBorrowAuthStatus(BorrowerStatusEnum.AUTH_RUN.getStatus());
    userInfoMapper.updateById(userInfo);
}

19.4.2、前端整合

pages/user/borrower.vue 脚本

save() {
  // debugger
  this.submitBtnDisabled = true
  this.$axios
    .$post('/api/core/borrower/auth/save', this.borrower)
    .then((response) => {
      this.active = 1
    })
},

19.5、获取借款人状态

19.5.1、获取借款人状态

1、BorrowerController

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

2、service

接口:BorrowerService

Integer getStatusByUserId(Long userId);

实现:BorrowerServiceImpl

@Override
public Integer getStatusByUserId(Long userId) {
    QueryWrapper<Borrower> borrowerQueryWrapper = new QueryWrapper<>();
    borrowerQueryWrapper.select("status").eq("user_id", userId);
    List<Object> objects = baseMapper.selectObjs(borrowerQueryWrapper);
    if(objects.size() == 0){
        //借款人尚未提交信息
        return BorrowerStatusEnum.NO_AUTH.getStatus();
    }
    Integer status = (Integer)objects.get(0);
    return status;
}

19.5.2、前端开发

pages/user/borrower.vue 脚本

将this.initSelected()在this.getUserInfo()中调用

created() {
  this.getUserInfo()
},

methods中添加方法:

//获取借款人信息
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
        }
    })
},

将 data() 中 active的初始化值设置为null

active: null, //步骤

20、借款额度审核

20.1、借款列表展示

20.1.1、需求

借款人列表

【金融项目】尚融宝项目(十)_第7张图片

额度审批

【金融项目】尚融宝项目(十)_第8张图片

额度审批的目标:

(1)在user_integral表中添加积分明细

(2)在user_info表中添加总积分(user_info表中的原始积分 + user_integral表中的积分明细之和 )

(3)修改borrower表的借款申请审核状态

(4)修改user_info表中的借款申请审核状态

20.1.2、后端实现

1、创建接口

创建 AdminBorrowerController

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

@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);
    }
}

2、创建Service方法

接口:BorrowerService

IPage<Borrower> listPage(Page<Borrower> pageParam, String keyword);

实现:BorrowerServiceImpl

@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.like("name", keyword)
        .or().like("id_card", keyword)
        .or().like("mobile", keyword)
        .orderByDesc("id");
    return baseMapper.selectPage(pageParam, borrowerQueryWrapper);
}

20.1.3、前端实现

1、创建页面组件

创建 src/views/core/borrower/list.vue

<template>
  <div class="app-container">
    借款用户列表
  div>
template>
<script>
export default {
  
}
script>

创建 src/views/core/borrower/detail.vue

<template>
  <div class="app-container">
    借款用户详情
  div>
template>
<script>
export default {
  
}
script>

2、配置路由

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
      }
    ]
 },

3、定义api

创建 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}
    })
  }
}

4、页面模板

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>

5、页面脚本

src/views/core/borrower/list.vue

<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>

20.2、借款人信息展示

20.2.1、后端实现

1、定义VO对象

BorrowerAttachVO

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

@Data
@ApiModel(value="借款人附件资料")
public class BorrowerAttachVO {
    @ApiModelProperty(value = "图片类型(idCard1:身份证正面,idCard2:身份证反面,house:房产证,car:车)")
    private String imageType;
    @ApiModelProperty(value = "图片路径")
    private String imageUrl;
}

BorrowerDetailVO

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

@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;
}

2、Controller

AdminBorrowerController

@ApiOperation("获取借款人信息")
@GetMapping("/show/{id}")
public R show(
    @ApiParam(value = "借款人id", required = true)
    @PathVariable Long id) {
    BorrowerDetailVO borrowerDetailVO = borrowerService.getBorrowerDetailVOById(id);
    return R.ok().data("borrowerDetailVO", borrowerDetailVO);
}

3、BorrowerService

接口

BorrowerDetailVO getBorrowerDetailVOById(Long id);

实现:调用BorrowerAttachService和DictService

@Resource
private DictService dictService;
@Resource
private BorrowerAttachService borrowerAttachService;

@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?"男":"女");
    //计算下拉列表选中内容
    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);
    
    //审批状态
    String status = BorrowerStatusEnum.getMsgByStatus(borrower.getStatus());
    borrowerDetailVO.setStatus(status);
    //获取附件VO列表
    List<BorrowerAttachVO> borrowerAttachVOList =  borrowerAttachService.selectBorrowerAttachVOList(id);
    borrowerDetailVO.setBorrowerAttachVOList(borrowerAttachVOList);
    return borrowerDetailVO;
}

4、DictService

接口

String getNameByParentDictCodeAndValue(String dictCode, Integer value);

实现

@Override
public String getNameByParentDictCodeAndValue(String dictCode, Integer value) {
    QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<Dict>();
    dictQueryWrapper.eq("dict_code", dictCode);
    Dict parentDict = baseMapper.selectOne(dictQueryWrapper);
    if(parentDict == null) {
        return "";
    }
    dictQueryWrapper = new QueryWrapper<>();
    dictQueryWrapper
        .eq("parent_id", parentDict.getId())
        .eq("value", value);
    Dict dict = baseMapper.selectOne(dictQueryWrapper);
    if(dict == null) {
        return "";
    }
    return dict.getName();
}

5、BorrowerAttachService

接口

List<BorrowerAttachVO> selectBorrowerAttachVOList(Long borrowerId);

实现

@Override
public List<BorrowerAttachVO> selectBorrowerAttachVOList(Long borrowerId) {
    QueryWrapper<BorrowerAttach> borrowerAttachQueryWrapper = new QueryWrapper<>();
    borrowerAttachQueryWrapper.eq("borrower_id", borrowerId);
    List<BorrowerAttach> borrowerAttachList = baseMapper.selectList(borrowerAttachQueryWrapper);
    List<BorrowerAttachVO> borrowerAttachVOList = new ArrayList<>();
    borrowerAttachList.forEach(borrowerAttach -> {
        BorrowerAttachVO borrowerAttachVO = new BorrowerAttachVO();
        borrowerAttachVO.setImageType(borrowerAttach.getImageType());
        borrowerAttachVO.setImageUrl(borrowerAttach.getImageUrl());
        borrowerAttachVOList.add(borrowerAttachVO);
    });
    return borrowerAttachVOList;
}

20.2.2、前端实现

1、定义api

api/borrower.js中添加方法

  show(id) {
    return request({
      url: `/admin/core/borrower/show/${id}`,
      method: 'get'
    })
  },

2、页面脚本

src/views/core/borrower/detail.vue

<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() {
    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>

3、页面模板

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>

20.3、借款额度审核

20.3.1、后端实现

1、创建VO

BorrowerApprovalVO

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

@Data
@ApiModel(description = "借款人审批")
public class BorrowerApprovalVO {
    @ApiModelProperty(value = "id")
    private Long borrowerId;
    @ApiModelProperty(value = "状态")
    private Integer status;
    @ApiModelProperty(value = "身份证信息是否正确")
    private Boolean isIdCardOk;
    @ApiModelProperty(value = "房产信息是否正确")
    private Boolean isHouseOk;
    @ApiModelProperty(value = "车辆信息是否正确")
    private Boolean isCarOk;
    @ApiModelProperty(value = "基本信息积分")
    private Integer infoIntegral;
}

2、controller

AdminBorrowerController

@ApiOperation("借款额度审批")
@PostMapping("/approval")
public R approval(@RequestBody BorrowerApprovalVO borrowerApprovalVO) {
    borrowerService.approval(borrowerApprovalVO);
    return R.ok().message("审批完成");
}

**3、BorrowerService **

接口

void approval(BorrowerApprovalVO borrowerApprovalVO);

实现

@Resource
private UserIntegralMapper userIntegralMapper;

@Transactional(rollbackFor = Exception.class)
@Override
public void approval(BorrowerApprovalVO borrowerApprovalVO) {
    
    if (borrowerApprovalVO.getInfoIntegral() < 30 || borrowerApprovalVO.getInfoIntegral() > 100) {
            throw new BusinessException("基本信息积分区间为30至100");
    }
    //借款人认证状态
    Long borrowerId = borrowerApprovalVO.getBorrowerId();
    Borrower borrower = baseMapper.selectById(borrowerId);
    borrower.setStatus(borrowerApprovalVO.getStatus());
    baseMapper.updateById(borrower);
    Long userId = borrower.getUserId();
    UserInfo userInfo = userInfoMapper.selectById(userId);
    //添加积分
    UserIntegral userIntegral = new UserIntegral();
    userIntegral.setUserId(userId);
    userIntegral.setIntegral(borrowerApprovalVO.getInfoIntegral());
    userIntegral.setContent("借款人基本信息");
    userIntegralMapper.insert(userIntegral);
    int curIntegral = userInfo.getIntegral() + borrowerApprovalVO.getInfoIntegral();
    if(borrowerApprovalVO.getIsIdCardOk()) {
        curIntegral += IntegralEnum.BORROWER_IDCARD.getIntegral();
        userIntegral = new UserIntegral();
        userIntegral.setUserId(userId);
        userIntegral.setIntegral(IntegralEnum.BORROWER_IDCARD.getIntegral());
        userIntegral.setContent(IntegralEnum.BORROWER_IDCARD.getMsg());
        userIntegralMapper.insert(userIntegral);
    }
    if(borrowerApprovalVO.getIsHouseOk()) {
        curIntegral += IntegralEnum.BORROWER_HOUSE.getIntegral();
        userIntegral = new UserIntegral();
        userIntegral.setUserId(userId);
        userIntegral.setIntegral(IntegralEnum.BORROWER_HOUSE.getIntegral());
        userIntegral.setContent(IntegralEnum.BORROWER_HOUSE.getMsg());
        userIntegralMapper.insert(userIntegral);
    }
    if(borrowerApprovalVO.getIsCarOk()) {
        curIntegral += IntegralEnum.BORROWER_CAR.getIntegral();
        userIntegral = new UserIntegral();
        userIntegral.setUserId(userId);
        userIntegral.setIntegral(IntegralEnum.BORROWER_CAR.getIntegral());
        userIntegral.setContent(IntegralEnum.BORROWER_CAR.getMsg());
        userIntegralMapper.insert(userIntegral);
    }
    userInfo.setIntegral(curIntegral);
    //修改审核状态
    userInfo.setBorrowAuthStatus(borrowerApprovalVO.getStatus());
    userInfoMapper.updateById(userInfo);
}

20.3.2、前端实现

1、定义api

api/borrower.js中添加方法

  approval(borrowerApproval) {
    return request({
      url: '/admin/core/borrower/approval',
      method: 'post',
      data: borrowerApproval
    })
  }

2、页面模板

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">(可获取30至100积分)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>

3、页面脚本

src/views/core/borrower/detail.vue

    approvalSubmit() {
      this.saveBtnDisabled = true
      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' })
      })
    }

4、查看用户积分

审批后可以在会员列表查看用户积分

【金融项目】尚融宝项目(十)_第9张图片
本文章参考B站 尚硅谷《尚融宝》Java微服务分布式金融项目,仅供个人学习使用,部分内容为本人自己见解,与尚硅谷无关。

你可能感兴趣的:(Java项目,金融,java,spring,boot,vue.js)