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

本文详细阐述了借款标的的创建流程,包括管理员审核通过后的标的生成、编号生成规则、后端服务实现(如LendStatusEnum枚举与LendNoUtils辅助类)、数据库操作(如检查利率精度)以及标的列表和详情展示的前后端交互。重点介绍了投资标的列表获取、审核状态转换和关键数据计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

23、标的管理

23.1、需求介绍

23.1.1、借款人申请借款

**1、需求描述 **

在这里插入图片描述

2、相关数据库表

lend:标的表

23.1.2、具体步骤

1、标的产生

管理员借款审核通过后,则产生新标的

2、查看标的列表

在这里插入图片描述

3、查看标的详情

在这里插入图片描述

23.2、生成新标的

23.2.1、后端实现

1、创建枚举

创建 LendStatusEnum

CHECK(0, "待发布"),
INVEST_RUN(1, "募资中"),
PAY_RUN(2, "还款中"),
PAY_OK(3, "已结清"),
FINISH(4, "结标"),
CANCEL(-1, "已撤标"),
;

2、定义编号辅助类

service-core中添加辅助类:util.LendNoUtils

3、Service

BorrowInfoServiceImpl 实现:

@Resource
private LendService lendService;

@Transactional(rollbackFor = Exception.class)
@Override
public void approval(BorrowInfoApprovalVO borrowInfoApprovalVO) {
    //修改借款信息状态
   ......
    //审核通过则创建标的
    if (borrowInfoApprovalVO.getStatus().intValue() == BorrowInfoStatusEnum.CHECK_OK.getStatus().intValue()) {
        //创建标的
        lendService.createLend(borrowInfoApprovalVO, borrowInfo);
    }
}

LendService 接口:

void createLend(BorrowInfoApprovalVO borrowInfoApprovalVO, BorrowInfo borrowInfo);

LendServiceImpl 实现:生成标的

@Override
public void createLend(BorrowInfoApprovalVO borrowInfoApprovalVO, BorrowInfo borrowInfo) {
    
    // 校验年化利率、平台服务费率(数据库修改为decimal(10,4),仅用年化利率与平台服务费率举例,其他涉及金额的操作都应该谨慎处理)
    String lendYearRate = borrowInfoApprovalVO.getLendYearRate().toPlainString();
    String[] lendYearRateSplit = lendYearRate.split("\\.");
    if (lendYearRateSplit.length > 1 && lendYearRateSplit[1].length() > 2) {
        throw new BusinessException("年化利率仅支持到小数点后两位");
    }
    String serviceRate = borrowInfoApprovalVO.getServiceRate().toPlainString();
    String[] serviceRateSplit = serviceRate.split("\\.");
    if (lendYearRateSplit.length > 1 && serviceRateSplit[1].length() > 2) {
        throw new BusinessException("平台服务费率仅支持到小数点后两位");
    }
    
    Lend lend = new Lend();
    lend.setUserId(borrowInfo.getUserId());
    lend.setBorrowInfoId(borrowInfo.getId());
    lend.setLendNo(LendNoUtils.getLendNo());//生成编号
    lend.setTitle(borrowInfoApprovalVO.getTitle());
    lend.setAmount(borrowInfo.getAmount());
    lend.setPeriod(borrowInfo.getPeriod());
    lend.setLendYearRate(borrowInfoApprovalVO.getLendYearRate().divide(new BigDecimal(100), 4, RoundingMode.DOWN));//从审批对象中获取
    lend.setServiceRate(borrowInfoApprovalVO.getServiceRate().divide(new BigDecimal(100), 4, RoundingMode.DOWN));//从审批对象中获取
    lend.setReturnMethod(borrowInfo.getReturnMethod());
    lend.setLowestAmount(new BigDecimal(100));
    lend.setInvestAmount(new BigDecimal(0));
    lend.setInvestNum(0);
    lend.setPublishDate(LocalDateTime.now());
    //起息日期
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    LocalDate lendStartDate = LocalDate.parse(borrowInfoApprovalVO.getLendStartDate(), dtf);
    lend.setLendStartDate(lendStartDate);
    //结束日期
    LocalDate lendEndDate = lendStartDate.plusMonths(borrowInfo.getPeriod());
    lend.setLendEndDate(lendEndDate);
    lend.setLendInfo(borrowInfoApprovalVO.getLendInfo());//描述
    //平台预期收益
    //        月年化 = 年化 / 12
    BigDecimal monthRate = lend.getServiceRate().divide(new BigDecimal(12), 8, RoundingMode.DOWN);
    //        平台收益 = 标的金额 * 月年化 * 期数
    BigDecimal expectAmount = lend.getAmount().multiply(monthRate).multiply(new BigDecimal(lend.getPeriod()));
    lend.setExpectAmount(expectAmount);
    //实际收益
    lend.setRealAmount(new BigDecimal(0));
    //状态
    lend.setStatus(LendStatusEnum.INVEST_RUN.getStatus());
    //审核时间
    lend.setCheckTime(LocalDateTime.now());
    //审核人
    lend.setCheckAdminId(1L);
    baseMapper.insert(lend);
}

23.3、标的列表

23.3.1、后端实现

1、扩展实体对象

在Lend类中扩展以下字段

@ApiModelProperty(value = "其他参数")
@TableField(exist = false)
private Map<String,Object> param = new HashMap<>();

2、Controller

添加 AdminLendController

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

@Api(tags = "标的管理")
@RestController
@RequestMapping("/admin/core/lend")
@Slf4j
public class AdminLendController {
    @Resource
    private LendService lendService;
    @ApiOperation("标的列表")
    @GetMapping("/list")
    public R list() {
        List<Lend> lendList = lendService.selectList();
        return R.ok().data("list", lendList);
    }
}

3、Service

接口:LendService

List<Lend> selectList();

实现:LendServiceImpl

@Resource
private DictService dictService;

@Override
public List<Lend> selectList() {
    List<Lend> lendList = baseMapper.selectList(null);
    lendList.forEach(lend -> {
        String returnMethod = dictService.getNameByParentDictCodeAndValue("returnMethod", lend.getReturnMethod());
        String status = LendStatusEnum.getMsgByStatus(lend.getStatus());
        lend.getParam().put("returnMethod", returnMethod);
        lend.getParam().put("status", status);
    });
    return lendList;
}

23.3.2、前端

1、创建页面组件

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

<template>
  <div class="app-container">
    标的列表
  </div>
</template>
<script>
export default {
  
}
</script>

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

<template>
  <div class="app-container">
    标的详情
  </div>
</template>
<script>
export default {
  
}
</script>

2、配置路由

src/router/index.js

  {
    path: '/core/lend',
    component: Layout,
    name: 'coreLend',
    meta: { title: '标的管理', icon: 'el-icon-s-flag' },
    alwaysShow: true,
    children: [
      {
        path: 'list',
        name: 'coreLendList',
        component: () => import('@/views/core/lend/list'),
        meta: { title: '标的列表' }
      },
      {
        path: 'detail/:id',
        name: 'coreLendDetail',
        component: () => import('@/views/core/lend/detail'),
        meta: { title: '标的详情' },
        hidden: true
      }
    ]
  },

3、定义api

创建 src/api/core/lend.js

import request from '@/utils/request'
export default {
  getList() {
    return request({
      url: `/admin/core/lend/list`,
      method: 'get'
    })
  }
}

4、页面脚本

src/views/core/lend/list.vue

<script>
import lendApi from '@/api/core/lend'
export default {
  data() {
    return {
      list: null // 列表
    }
  },
  created() {
    this.fetchData()
  },
  methods: {
    // 加载列表数据
    fetchData() {
      lendApi.getList().then(response => {
        this.list = response.data.list
      })
    }
  }
}
</script>

5、页面模板

src/views/core/lend/list.vue

<template>
  <div class="app-container">
    <!-- 列表 -->
    <el-table :data="list" stripe>
      <el-table-column type="index" label="序号" width="60" align="center" />
      <el-table-column prop="lendNo" label="标的编号" width="160" />
      <el-table-column prop="amount" label="标的金额" />
      <el-table-column prop="period" label="投资期数" />
      <el-table-column label="年化利率">
        <template slot-scope="scope">
          {{ scope.row.lendYearRate * 100 }}%
        </template>
      </el-table-column>
      <el-table-column prop="investAmount" label="已投金额" />
      <el-table-column prop="investNum" label="投资人数" />
      <el-table-column prop="publishDate" label="发布时间" width="150" />
      <el-table-column prop="lendStartDate" label="开始日期" />
      <el-table-column prop="lendEndDate" label="结束日期" />
      <el-table-column prop="param.returnMethod" label="还款方式" />
      <el-table-column prop="param.status" label="状态" />

      <el-table-column label="操作" width="150" align="center">
        <template slot-scope="scope">
          <el-button type="primary" size="mini">
            <router-link :to="'/core/lend/detail/' + scope.row.id">
              查看
            </router-link>
          </el-button>

          <el-button
            v-if="scope.row.status == 1"
            type="warning"
            size="mini"
            @click="makeLoan(scope.row.id)"
          >
            放款
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

23.3、标的详情

23.3.1、后端实现

1、Controller

AdminLendController

@ApiOperation("获取标的信息")
@GetMapping("/show/{id}")
public R show(
    @ApiParam(value = "标的id", required = true)
    @PathVariable Long id) {
    Map<String, Object> result = lendService.getLendDetail(id);
    return R.ok().data("lendDetail", result);
}

2、Service

接口:LendService

Map<String, Object> getLendDetail(Long id);

实现:LendServiceImpl

@Resource
private BorrowerMapper borrowerMapper;
@Resource
private BorrowerService borrowerService;

@Override
public Map<String, Object> getLendDetail(Long id) {
    
    //查询标的对象
    Lend lend = baseMapper.selectById(id);
    //组装数据
    String returnMethod = dictService.getNameByParentDictCodeAndValue("returnMethod", lend.getReturnMethod());
    String status = LendStatusEnum.getMsgByStatus(lend.getStatus());
    lend.getParam().put("returnMethod", returnMethod);
    lend.getParam().put("status", status);
    //根据user_id获取借款人对象
    QueryWrapper<Borrower> borrowerQueryWrapper = new QueryWrapper<Borrower>();
    borrowerQueryWrapper.eq("user_id", lend.getUserId());
    Borrower borrower = borrowerMapper.selectOne(borrowerQueryWrapper);
    //组装借款人对象
    BorrowerDetailVO borrowerDetailVO = borrowerService.getBorrowerDetailVOById(borrower.getId());
    //组装数据
    Map<String, Object> result = new HashMap<>();
    result.put("lend", lend);
    result.put("borrower", borrowerDetailVO);
    return result;
}

23.3.2、前端

1、定义api

src/api/core/lend.js

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

2、页面脚本

src/views/core/lend/detail.vue

<script>
import lendApi from '@/api/core/lend'
import '@/styles/show.css'
export default {
  data() {
    return {
      lendDetail: {
        lend: {
          param: {}
        },
        borrower: {}
      }
    }
  },
  created() {
    if (this.$route.params.id) {
      this.fetchDataById()
    }
  },
  methods: {
    fetchDataById() {
      lendApi.show(this.$route.params.id).then(response => {
        this.lendDetail = response.data.lendDetail
      })
    },
    back() {
      this.$router.push({ path: '/core/lend/list' })
    }
  }
}
</script>

3、页面模板

src/views/core/lend/detail.vue

<template>
  <div class="app-container">
    <h4>标的信息</h4>
    <table
      class="table table-striped table-condenseda table-bordered"
      width="100%"
    >
      <tbody>
        <tr>
          <th width="15%">标的编号</th>
          <td width="35%">
            <b>{{ lendDetail.lend.lendNo }}</b>
          </td>
          <th width="15%">标题</th>
          <td width="35%">{{ lendDetail.lend.title }}</td>
        </tr>
        <tr>
          <th>标的金额</th>
          <td>{{ lendDetail.lend.amount }}元</td>
          <th>投资期数</th>
          <td>{{ lendDetail.lend.period }}个月</td>
        </tr>
        <tr>
          <th>年化利率</th>
          <td>
            标的:{{ lendDetail.lend.lendYearRate * 100 }}%
            <br />
            平台:{{ lendDetail.lend.serviceRate * 100 }}%
          </td>
          <th>还款方式</th>
          <td>{{ lendDetail.lend.param.returnMethod }}</td>
        </tr>

        <tr>
          <th>最低投资金额</th>
          <td>{{ lendDetail.lend.lowestAmount }}元</td>
          <th>发布日期</th>
          <td>{{ lendDetail.lend.publishDate }}</td>
        </tr>
        <tr>
          <th>开始日期</th>
          <td>{{ lendDetail.lend.lendStartDate }}</td>
          <th>结束日期</th>
          <td>{{ lendDetail.lend.lendEndDate }}</td>
        </tr>
        <tr>
          <th>已投金额</th>
          <td>
            <b>{{ lendDetail.lend.investAmount }}元</b>
          </td>
          <th>投资人数</th>
          <td>{{ lendDetail.lend.investNum }}人</td>
        </tr>
        <tr>
          <th>状态</th>
          <td>
            <b>{{ lendDetail.lend.param.status }}</b>
          </td>
          <th>创建时间</th>
          <td>{{ lendDetail.lend.createTime }}</td>
        </tr>
        <tr>
          <th>说明</th>
          <td colspan="3">
            <b>{{ lendDetail.lend.lendInfo }}</b>
          </td>
        </tr>
      </tbody>
    </table>
      
    <h4>平台收益信息</h4>
    <table
      class="table table-striped table-condenseda table-bordered"
      width="100%"
    >
      <tbody>
        <tr>
          <th width="15%">标的预期收益</th>
          <td width="35%">
            <b>{{ lendDetail.lend.expectAmount }}元</b>
          </td>
          <th width="15%">标的已获取收益</th>
          <td width="35%">{{ lendDetail.lend.realAmount }}元</td>
        </tr>
      </tbody>
    </table>

    <h4>借款人信息</h4>
    <table
      class="table table-striped table-condenseda table-bordered"
      width="100%"
    >
      <tbody>
        <tr>
          <th width="15%">借款人</th>
          <td width="35%">
            <b>{{ lendDetail.borrower.name }}</b>
          </td>
          <th width="15%">手机</th>
          <td width="35%">{{ lendDetail.borrower.mobile }}</td>
        </tr>
        <tr>
          <th>身份证</th>
          <td>{{ lendDetail.borrower.idCard }}</td>
          <th>性别</th>
          <td>{{ lendDetail.borrower.sex }}</td>
        </tr>
        <tr>
          <th>年龄</th>
          <td>{{ lendDetail.borrower.age }}</td>
          <th>是否结婚</th>
          <td>{{ lendDetail.borrower.marry }}</td>
        </tr>
        <tr>
          <th>学历</th>
          <td>{{ lendDetail.borrower.education }}</td>
          <th>行业</th>
          <td>{{ lendDetail.borrower.industry }}</td>
        </tr>
        <tr>
          <th>月收入</th>
          <td>{{ lendDetail.borrower.income }}</td>
          <th>还款来源</th>
          <td>{{ lendDetail.borrower.returnSource }}</td>
        </tr>
        <tr>
          <th>创建时间</th>
          <td>{{ lendDetail.borrower.createTime }}</td>
          <th>状态</th>
          <td>{{ lendDetail.borrower.status }}</td>
        </tr>
      </tbody>
    </table>

    <el-row style="text-align:center;margin-top: 40px;">
      <el-button @click="back">
        返回
      </el-button>
    </el-row>
  </div>
</template>

24、我要投资

24.1、投资标的列表

24.1.1、需求

在这里插入图片描述

24.1.2、后端实现

Controller

LendController中创建list方法

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

@Api(tags = "标的")
@RestController
@RequestMapping("/api/core/lend")
@Slf4j
public class LendController {
    @Resource
    private LendService lendService;
    @ApiOperation("获取标的列表")
    @GetMapping("/list")
    public R list() {
        List<Lend> lendList = lendService.selectList();
        return R.ok().data("lendList", lendList);
    }
}

24.1.3、前端整合

pages/lend/index.vue

脚本

此处使用了服务器端渲染

async asyncData({ $axios }) {
    let response = await $axios.$get('/api/core/lend/list')
    return {
      lendList: response.data.lendList,
    }
},

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值