13、用户注册

13.1、前端整合发送短信验证码

13.1.1、运行srb-site

13.1.1.1、解压

srb_site

13.1.1.2、运行

npm run dev

13.1.2、前端页面整合

pages/register.vue

  methods: {//发短信  send() {if (!this.userInfo.mobile) {this.$message.error('请输入手机号')return}//防止重复提交if (this.sending) returnthis.sending = true//倒计时this.timeDown()//远程调用发送短信的接口this.$axios.$get('/api/sms/send/' + this.userInfo.mobile).then((response) => {this.$message.success(response.message)})},//倒计时timeDown() {console.log('进入倒计时')this.leftSecond = this.second//创建定时器const timmer = setInterval(() => {//计数器减一this.leftSecond--if (this.leftSecond <= 0) {//停止定时器clearInterval(timmer)//还原计数器this.leftSecond = this.second//还原按钮状态this.sending = false}}, 1000)},},

13.2、实现用户注册

13.2.1、需求

13.2.2、后端接口

13.2.2.1、创建VO对象

service-core中创建vo

package com.atguigu.srb.core.pojo.vo;
@Data
@ApiModel(description="注册对象")
public class RegisterVO {@ApiModelProperty(value = "用户类型")private Integer userType;@ApiModelProperty(value = "手机号")private String mobile;@ApiModelProperty(value = "验证码")private String code;@ApiModelProperty(value = "密码")private String password;
}

13.2.2.2、定义常量

UserInfo中添加常量

public static final Integer STATUS_NORMAL = 1;
public static final Integer STATUS_LOCKED = 0;

13.2.2.3、引入MD5工具类

guigu-common中util包,引入工具类:

MD5.java:MD5加密

13.2.2.4、Controller

注意:将controller包中的UserInfoController移植到controller.api包下

package com.atguigu.srb.core.controller.api;@Api(tags = "会员接口")
@RestController
@RequestMapping("/api/core/userInfo")
@Slf4j
@CrossOrigin
public class UserInfoController {@Resourceprivate UserInfoService userInfoService;@Resourceprivate RedisTemplate redisTemplate;@ApiOperation("会员注册")@PostMapping("/register")public R register(@RequestBody RegisterVO registerVO){String mobile = registerVO.getMobile();String password = registerVO.getPassword();String code = registerVO.getCode();//MOBILE_NULL_ERROR(-202, "手机号不能为空"),Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);//MOBILE_ERROR(-203, "手机号不正确"),Assert.isTrue(RegexValidateUtils.checkCellphone(mobile), ResponseEnum.MOBILE_ERROR);//PASSWORD_NULL_ERROR(-204, "密码不能为空"),Assert.notEmpty(password, ResponseEnum.PASSWORD_NULL_ERROR);//CODE_NULL_ERROR(-205, "验证码不能为空"),Assert.notEmpty(code, ResponseEnum.CODE_NULL_ERROR);//校验验证码String codeGen = (String)redisTemplate.opsForValue().get("srb:sms:code:" + mobile);//CODE_ERROR(-206, "验证码不正确"),Assert.equals(code, codeGen, ResponseEnum.CODE_ERROR);//注册userInfoService.register(registerVO);return R.ok().message("注册成功");}
}

13.2.2.5、Service

接口:UserInfoService

package com.atguigu.srb.core.service;public interface UserInfoService extends IService<UserInfo> {void register(RegisterVO registerVO);
}

实现:UserInfoServiceImpl

package com.atguigu.srb.core.service.impl;@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {@Resourceprivate UserAccountMapper userAccountMapper;@Transactional(rollbackFor = {Exception.class})@Overridepublic void register(RegisterVO registerVO) {//判断用户是否被注册QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();queryWrapper.eq("mobile", registerVO.getMobile());Integer count = baseMapper.selectCount(queryWrapper);//MOBILE_EXIST_ERROR(-207, "手机号已被注册"),Assert.isTrue(count == 0, ResponseEnum.MOBILE_EXIST_ERROR);//插入用户基本信息UserInfo userInfo = new UserInfo();userInfo.setUserType(registerVO.getUserType());userInfo.setNickName(registerVO.getMobile());userInfo.setName(registerVO.getMobile());userInfo.setMobile(registerVO.getMobile());userInfo.setPassword(MD5.encrypt(registerVO.getPassword()));userInfo.setStatus(UserInfo.STATUS_NORMAL); //正常//设置一张静态资源服务器上的头像图片userInfo.setHeadImg("https://srb-file.oss-cn-beijing.aliyuncs.com/avatar/07.jpg");baseMapper.insert(userInfo);//创建会员账户UserAccount userAccount = new UserAccount();userAccount.setUserId(userInfo.getId());userAccountMapper.insert(userAccount);}
}

13.2.3、前端整合

pages/register.vue

//注册
register() {this.$axios.$post('/api/core/userInfo/register', this.userInfo).then((response) => {this.step = 2})
},

14、用户认证

14.1、实现用户登录

14.1.1、需求

14.1.2、后端的接口

14.1.2.1、集成JWT

service-base中添加依赖

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId>
</dependency>

14.1.2.2、JWT工具

service-base中添加util包

添加JwtUtils类

14.1.2.3、创建VO对象

service-core中创建登录对象

package com.atguigu.srb.core.pojo.vo;@Data
@ApiModel(description="登录对象")
public class LoginVO {@ApiModelProperty(value = "用户类型")private Integer userType;@ApiModelProperty(value = "手机号")private String mobile;@ApiModelProperty(value = "密码")private String password;
}

用户信息对象

package com.atguigu.srb.core.pojo.vo;@Data
@ApiModel(description="用户信息对象")
public class UserInfoVO {@ApiModelProperty(value = "用户姓名")private String name;@ApiModelProperty(value = "用户昵称")private String nickName;@ApiModelProperty(value = "头像")private String headImg;@ApiModelProperty(value = "手机号")private String mobile;@ApiModelProperty(value = "1:出借人 2:借款人")private Integer userType;@ApiModelProperty(value = "JWT访问令牌")private String token;
}

14.1.2.4、Controller

UserInfoController

@ApiOperation("会员登录")
@PostMapping("/login")
public R login(@RequestBody LoginVO loginVO, HttpServletRequest request) {String mobile = loginVO.getMobile();String password = loginVO.getPassword();Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);Assert.notEmpty(password, ResponseEnum.PASSWORD_NULL_ERROR);String ip = request.getRemoteAddr();UserInfoVO userInfoVO = userInfoService.login(loginVO, ip);return R.ok().data("userInfo", userInfoVO);
}

14.1.2.5、Service

接口:UserInfoService

UserInfoVO login(LoginVO loginVO, String ip);

实现:UserInfoServiceImpl

@Resource
private UserLoginRecordMapper userLoginRecordMapper;@Transactional( rollbackFor = {Exception.class})
@Override
public UserInfoVO login(LoginVO loginVO, String ip) {String mobile = loginVO.getMobile();String password = loginVO.getPassword();Integer userType = loginVO.getUserType();//获取会员QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();queryWrapper.eq("mobile", mobile);queryWrapper.eq("user_type", userType);UserInfo userInfo = baseMapper.selectOne(queryWrapper);//用户不存在//LOGIN_MOBILE_ERROR(-208, "用户不存在"),Assert.notNull(userInfo, ResponseEnum.LOGIN_MOBILE_ERROR);//校验密码//LOGIN_PASSWORD_ERROR(-209, "密码不正确"),Assert.equals(MD5.encrypt(password), userInfo.getPassword(), ResponseEnum.LOGIN_PASSWORD_ERROR);//用户是否被禁用//LOGIN_DISABLED_ERROR(-210, "用户已被禁用"),Assert.equals(userInfo.getStatus(), UserInfo.STATUS_NORMAL, ResponseEnum.LOGIN_LOKED_ERROR);//记录登录日志UserLoginRecord userLoginRecord = new UserLoginRecord();userLoginRecord.setUserId(userInfo.getId());userLoginRecord.setIp(ip);userLoginRecordMapper.insert(userLoginRecord);//生成tokenString token = JwtUtils.createToken(userInfo.getId(), userInfo.getName());UserInfoVO userInfoVO = new UserInfoVO();userInfoVO.setToken(token);userInfoVO.setName(userInfo.getName());userInfoVO.setNickName(userInfo.getNickName());userInfoVO.setHeadImg(userInfo.getHeadImg());userInfoVO.setMobile(userInfo.getMobile());userInfoVO.setUserType(userType);return userInfoVO;
}

14.1.3、前端整合

14.1.3.1、登录脚本

pages/login.vue

methods: {//登录login() {this.$axios.$post('/api/core/userInfo/login', this.userInfo).then((response) => {// 把用户信息存在cookie中cookie.set('userInfo', response.data.userInfo)window.location.href = '/user'})},
},

14.1.2.2、页面头信息

components/AppHeader.vue

脚本

<script>
import cookie from 'js-cookie'
export default {data() {return {userInfo: null,}},mounted() {this.showInfo()},methods: {//显示用户信息  showInfo() {// debuggerlet userInfo = cookie.get('userInfo')if (!userInfo) {console.log('cookie不存在')this.userInfo = nullreturn}  userInfo = JSON.parse(userInfo)  this.userInfo = userInfo},//退出  logout() {cookie.set('userInfo', '')//跳转页面window.location.href = '/login'},},
}
</script>

14.2、校验用户登录

14.2.1、后端的接口

14.2.1.1、添加令牌校验接口

service-core 中 UserInfoController添加令牌校验接口

@ApiOperation("校验令牌")
@GetMapping("/checkToken")
public R checkToken(HttpServletRequest request) {String token = request.getHeader("token");boolean result = JwtUtils.checkToken(token);if(result){return R.ok();}else{//LOGIN_AUTH_ERROR(-211, "未登录"),return R.setResult(ResponseEnum.LOGIN_AUTH_ERROR);}
}

14.2.1.2、Swagger请求头添加header

step1:service-base添加依赖

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.2</version>
</dependency>

step2:访问

http://localhost:8110/doc.html

step3:添加全局参数

step4:测试

14.2.2、前端整合

14.2.2.1、优化showInfo

components/AppHeader.vue

脚本

showInfo() {// debuggerlet userInfo = cookie.get('userInfo')if (!userInfo) {console.log('cookie不存在')this.userInfo = nullreturn}userInfo = JSON.parse(userInfo)//先在服务器端校验tokenthis.$axios({url: '/api/core/userInfo/checkToken',method: 'get',headers: {//如果token校验成功,再展示user信息token: userInfo.token,},}).then((response) => {console.log('校验成功')this.userInfo = userInfo})
},

14.2.2.2、axios请求拦截(了解)

可以在axios请求拦截器中统一添加header

  $axios.onRequest((config) => {// 添加请求头:tokenlet userInfo = cookie.get('userInfo')if (userInfo) {console.log('添加header')userInfo = JSON.parse(userInfo)config.headers['token'] = userInfo.token}console.log('Making request to ' + config.url)})

14.2.2.3、axios响应拦截(了解)

plugins/axios.js:处理未登录状况

  $axios.onResponse((response) => {console.log('Reciving resposne', response)if (response.data.code === 0) {return response} else if (response.data.code === -211) {console.log('token校验失败')cookie.set('userInfo', '')//debugger//跳转到登录页面window.location.href = '/login'} else {Message({message: response.data.message,type: 'error',duration: 5 * 1000,})return Promise.reject(response)}})

15、会员管理

15.1、会员分页列表

15.1.1、需求

15.1.2、后端接口实现

15.1.2.1、创建查询对象

UserInfoQuery

package com.atguigu.srb.core.pojo.query;@Data
@ApiModel(description="会员搜索对象")
public class UserInfoQuery {@ApiModelProperty(value = "手机号")private String mobile;@ApiModelProperty(value = "状态")private Integer status;@ApiModelProperty(value = "1:出借人 2:借款人")private Integer userType;
}

15.1.2.2、Service

接口:UserInfoService

IPage<UserInfo> listPage(Page<UserInfo> pageParam, UserInfoQuery userInfoQuery);

实现:UserInfoServiceImpl

@Override
public IPage<UserInfo> listPage(Page<UserInfo> pageParam, UserInfoQuery userInfoQuery) {String mobile = userInfoQuery.getMobile();Integer status = userInfoQuery.getStatus();Integer userType = userInfoQuery.getUserType();QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();if(userInfoQuery == null){return baseMapper.selectPage(pageParam, null);}userInfoQueryWrapper.eq(StringUtils.isNotBlank(mobile), "mobile", mobile).eq(status != null, "status", userInfoQuery.getStatus()).eq(userType != null, "user_type", userType);return baseMapper.selectPage(pageParam, userInfoQueryWrapper);
}

15.1.2.3、Controller

AdminUserInfoController

package com.atguigu.srb.core.controller.admin;@Api(tags = "会员管理")
@RestController
@RequestMapping("/admin/core/userInfo")
@Slf4j
@CrossOrigin
public class AdminUserInfoController {@Resourceprivate UserInfoService userInfoService;@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)UserInfoQuery userInfoQuery) {Page<UserInfo> pageParam = new Page<>(page, limit);IPage<UserInfo> pageModel = userInfoService.listPage(pageParam, userInfoQuery);return R.ok().data("pageModel", pageModel);}
}

15.1.2.4、LocalDateTime的json格式化问题

service-base中添加json格式化配置文件

package com.atguigu.srb.base.config;import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class LocalDateTimeSerializerConfig {@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")private String pattern;public LocalDateTimeSerializer localDateTimeDeserializer() {return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));}@Beanpublic Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());}
}

上面的方案全局生效,当全局的格式化方式无法满足我们需求时,我们对日期格式要做特殊的处理:在类的属性上添加注解

@JsonFormat(pattern = "yyyy-MM-dd")
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;

15.1.3、前端整合

15.1.3.1、创建vue组件

core/user-info/list.vue

<template><div class="app-container">user list</div>
</template>

15.1.3.2、配置路由

  {path: '/core/user-info',component: Layout,redirect: '/core/user-info/list',name: 'coreUserInfo',meta: { title: '会员管理', icon: 'user' },alwaysShow: true,children: [{path: 'list',name: 'coreUserInfoList',component: () => import('@/views/core/user-info/list'),meta: { title: '会员列表' }}]},

15.1.3.3、定义api模块

创建文件 src/api/core/user-info.js

import request from '@/utils/request'
export default {getPageList(page, limit, searchObj) {return request({url: `/admin/core/userInfo/list/${page}/${limit}`,method: 'get',params: searchObj})}
}

15.1.3.4、定义页面组件脚本

src/views/core/user-info/list.vue

<script>
import userInfoApi from '@/api/core/user-info'
export default {data() {return {list: null, // 数据列表total: 0, // 数据库中的总记录数page: 1, // 默认页码limit: 10, // 每页记录数searchObj: {}, // 查询条件loginRecordList: [], //会员登录日志dialogTableVisible: false //对话框是否显示}},created() {// 当页面加载时获取数据this.fetchData()},methods: {fetchData() {userInfoApi.getPageList(this.page, this.limit, this.searchObj).then(response => {this.list = response.data.pageModel.recordsthis.total = response.data.pageModel.total})},// 每页记录数改变,size:回调参数,表示当前选中的“每页条数”changePageSize(size) {this.limit = sizethis.fetchData()},// 改变页码,page:回调参数,表示当前选中的“页码”changeCurrentPage(page) {this.page = pagethis.fetchData()},// 重置表单resetData() {this.searchObj = {}this.fetchData()}}
}
</script>

15.1.3.5、定义页面组件模板

src/views/core/user-info/list.vue

<template><div class="app-container"><!--查询表单--><el-form :inline="true" class="demo-form-inline"><el-form-item label="手机号"><el-input v-model="searchObj.mobile" placeholder="手机号" /></el-form-item><el-form-item label="用户类型"><el-select v-model="searchObj.userType" placeholder="请选择" clearable><el-option label="投资人" value="1" /><el-option label="借款人" value="2" /></el-select></el-form-item><el-form-item label="用户状态"><el-select v-model="searchObj.status" placeholder="请选择" clearable><el-option label="正常" value="1" /><el-option label="锁定" value="0" /></el-select></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" border stripe><el-table-column label="#" width="50"><template slot-scope="scope">{{ (page - 1) * limit + scope.$index + 1 }}</template></el-table-column><el-table-column label="用户类型" width="100"><template slot-scope="scope"><el-tag v-if="scope.row.userType === 1" type="success" size="mini">投资人</el-tag><el-tagv-else-if="scope.row.userType === 2"type="warning"size="mini">借款人</el-tag></template></el-table-column><el-table-column prop="mobile" label="手机号" /><el-table-column prop="name" label="用户姓名" /><el-table-column prop="idCard" label="身份证号" /><el-table-column prop="integral" label="用户积分" /><el-table-column prop="createTime" label="注册时间" width="100" /><el-table-column label="绑定状态" width="90"><template slot-scope="scope"><el-tag v-if="scope.row.bindStatus === 0" type="warning" size="mini">未绑定</el-tag><el-tagv-else-if="scope.row.bindStatus === 1"type="success"size="mini">已绑定</el-tag><el-tag v-else type="danger" size="mini">绑定失败</el-tag></template></el-table-column><el-table-column label="用户状态" width="90"><template slot-scope="scope"><el-tag v-if="scope.row.status === 0" type="danger" size="mini">锁定</el-tag><el-tag v-else type="success" size="mini">正常</el-tag></template></el-table-column></el-table><!-- 分页组件 --><el-pagination:current-page="page":total="total":page-size="limit":page-sizes="[10, 20]"style="padding: 30px 0; "layout="total, sizes, prev, pager, next, jumper"@size-change="changePageSize"@current-change="changeCurrentPage"/></div>
</template>

15.2、锁定和解锁

15.2.1**、后端接口实现**

15.2.1.1、Service

接口:UserInfoService

void lock(Long id, Integer status);

实现:UserInfoServiceImpl

@Override
public void lock(Long id, Integer status) {//        UserInfo userInfo = this.getById(id);//select//        userInfo.setStatus(1);//        this.updateById(userInfo);//updateUserInfo userInfo = new UserInfo();userInfo.setId(id);userInfo.setStatus(status);baseMapper.updateById(userInfo);
}

15.2.1.2、Controller

AdminUserInfoController

@ApiOperation("锁定和解锁")
@PutMapping("/lock/{id}/{status}")
public R lock(@ApiParam(value = "用户id", required = true)@PathVariable("id") Long id,@ApiParam(value = "锁定状态(0:锁定 1:解锁)", required = true)@PathVariable("status") Integer status){userInfoService.lock(id, status);return R.ok().message(status==1?"解锁成功":"锁定成功");
}

15.2.2、前端整合

15.2.2.1、定义api

src/api/core/user-info.js

  lock(id, status) {return request({url: `/admin/core/userInfo/lock/${id}/${status}`,method: 'put'})}

15.2.2.2、定义页面组件脚本

src/views/core/user-info/list.vue

    // 锁定和解锁lock(id, status) {userInfoApi.lock(id, status).then(response => {this.$message.success(response.message)this.fetchData()})}

15.2.2.3、定义页面组件模板

src/views/core/user-info/list.vue:

<el-table-column label="操作" align="center" width="200"><template slot-scope="scope"><el-buttonv-if="scope.row.status == 1"type="primary"size="mini"@click="lock(scope.row.id, 0)">锁定</el-button><el-buttonv-elsetype="danger"size="mini"@click="lock(scope.row.id, 1)">解锁</el-button></template>
</el-table-column>

15.3、显示登录日志

15.3.1、后端接口实现

15.3.1.1、Controller

AdminUserLoginRecordController

package com.atguigu.srb.core.controller.admin;@Api(tags = "会员登录日志接口")
@RestController
@RequestMapping("/admin/core/userLoginRecord")
@Slf4j
@CrossOrigin
public class AdminUserLoginRecordController {@Resourceprivate UserLoginRecordService userLoginRecordService;@ApiOperation("获取会员登录日志列表")@GetMapping("/listTop50/{userId}")public R listTop50(@ApiParam(value = "用户id", required = true)@PathVariable Long userId) {List<UserLoginRecord> userLoginRecordList = userLoginRecordService.listTop50(userId);return R.ok().data("list", userLoginRecordList);}
}

15.3.1.2、Service

接口:UserLoginRecordService

List<UserLoginRecord> listTop50(Long userId);

实现:UserLoginRecordServiceImpl

@Override
public List<UserLoginRecord> listTop50(Long userId) {QueryWrapper<UserLoginRecord> userLoginRecordQueryWrapper = new QueryWrapper<>();userLoginRecordQueryWrapper.eq("user_id", userId).orderByDesc("id").last("limit 50");List<UserLoginRecord> userLoginRecords = baseMapper.selectList(userLoginRecordQueryWrapper);return userLoginRecords;
}

15.3.2、前端整合

15.3.2.1、定义api

src/api/core/user-info.js

  getuserLoginRecordTop50(userId) {return request({url: `/admin/core/userLoginRecord/listTop50/${userId}`,method: 'get'})}

15.3.2.2、定义页面组件脚本

    // 根据id查询会员日志记录showLoginRecord(id) {//打开对话框this.dialogTableVisible = true//加载数据列表userInfoApi.getuserLoginRecordTop50(id).then(response => {this.loginRecordList = response.data.list})}

15.3.2.3、定义页面组件模板

src/views/core/user-info/list.vue

在操作列添加按钮:

<el-buttontype="primary"size="mini"@click="showLoginRecord(scope.row.id)">登录日志
</el-button>

在模板最后添加对话框:

<!-- 用户登录日志 -->
<el-dialog title="用户登录日志" :visible.sync="dialogTableVisible"><el-table :data="loginRecordList" border stripe><el-table-column type="index" /><el-table-column prop="ip" label="IP" /><el-table-column prop="createTime" label="登录时间" /></el-table>
</el-dialog>

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

【金融项目】尚融宝项目(七)相关推荐

  1. 【金融项目】尚融宝项目(一)

    1.尚融宝项目简介 1.1.前言 尚融宝项目是一个网络借贷信息中介服务平台,为个人投资者.个人融资用户和小微企业提供专业的线上信贷及出借撮合服务. 行业案例:人人贷 https://www.renre ...

  2. 【金融项目】尚融宝项目(六)

    11.访问令牌 11.1.单点登录 11.1.1.用户身份认证 11.1.1.1.单一服务器模式 一般过程如下: 用户向服务器发送用户名和密码. 验证服务器后,相关数据(如用户名,用户角色等)将保存在 ...

  3. 【金融项目】尚融宝项目(十四)

    27.放款 27.1.需求介绍 27.1.1.平台放款 1.需求描述 标的募资时间到,平台会操作放款或撤标,如果达到放款条件则操作放款 说明:撤标过程与放款过程一致,处理业务相对简单,只是将出借金额返 ...

  4. 【金融项目】尚融宝项目(十六)

    31.RabbitMQ 31.1.整合Rabbit MQ发送短信 31.1.1.MQ服务器设置 1.访问MQ控制台 http://192.168.100.103:15672 2.创建用户 创建用户 s ...

  5. 【金融项目】尚融宝项目(十五)

    29.提现和还款 29.1.提现 29.1.1.需求 放款成功后,借款人可以申请提现. 参考<汇付宝商户账户技术文档>3.15用户申请提现 29.1.2.前端整合 pages/user/w ...

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

    19.申请借款额度 19.1.需求介绍 19.1.1.借款人申请额度 1.需求描述 平台管理员根据借款人个人信息设置积分,通过积分规则借款人可以获取额度. 2.相关数据库表 19.1.2.具体步骤 s ...

  7. 【金融项目】尚融宝项目(四)

    6.Alibaba EasyExcel 6.1.EasyExcel简介 6.1.1.Excel导入导出的应用场景 6.1.1.1.数据导入 减轻录入工作量 6.1.1.2.数据导出 统计信息归档 6. ...

  8. 【金融项目】尚融宝项目(九)

    18.账户绑定 18.1.需求介绍 18.1.1.运行汇付宝 1.数据库 hfb.sql 2.程序 hfb 3.数据库配置 application-dev.yml 中修改数据库配置 4.启动程序 端口 ...

  9. 【金融项目】尚融宝项目(八)

    16.服务调用 16.1.注册中心和服务发现 16.1.1.运行Nacos注册中心 16.1.1.1.Nacos下载和安装 下载地址:https://github.com/alibaba/nacos/ ...

  10. 【金融项目】尚融宝项目(十一)

    21.借款申请 21.1.需求介绍 21.1.1.借款人申请借款 1.需求描述 2.相关数据库表 21.1.2.具体步骤 step1:借款人点击"我要借款" step2:展示借款信 ...

最新文章

  1. 【Socket研究】~。~ Scoket开发蛋疼笔记 Silverlight
  2. 轻量级的jQuery表单验证插件 - HAPPY.js
  3. 从自定义TagLayout看自定义布局的一般步骤[手动加精]
  4. NioEventLoop 的实例化过程
  5. HDU2608 0 or 1
  6. MySQL与MongoDB的区别
  7. 【转】理解字节序 大端字节序和小端字节序
  8. Python生态概览(三):图形用户界面开发库、游戏开发库、虚拟现实库、图形艺术库
  9. rust笔记9 错误处理
  10. 2017全球超算峰会召开 联想以智能超算赋能AI时代
  11. php清空单例属性_PHP单例模式--典型的三私一公
  12. 中广核继续领航光伏风向标 630后首个重大招标项目
  13. Nebula3资源子系统
  14. 【RWM】基于matlab路由无线传感器网络模拟随机路点运动模型【含Matlab源码 1565期】
  15. 第一次在中文维基百科上创建条目
  16. 我99年想出来00年发表的一个概念,被百度百科引用了
  17. Teigha 40010 保存设置Wipeout时的边界显示问题
  18. Proxy Error错误解决方法
  19. 苹果html 闪退,苹果打开软件闪退是怎么回事_苹果手机一打开软件就闪退如何解决-win7之家...
  20. SAP那些事-生产订单结算规则修改

热门文章

  1. BZOJ3162: 独钓寒江雪
  2. 关于云流化系统-实时云渲染延时性的讨论
  3. 计算机高级语言程序的流程控制结构,汇编语言(四) - 程序结构
  4. 动画云渲染【渲染101】渲染小提示
  5. springboot 删除路径下面所有文件_[原创]springboot 中 resources 资源目录里面的文件夹压缩下载...
  6. sqlrelay mysql_SQL Relay使用
  7. android是什么意思
  8. matlab处理多光谱,多光谱数据处理教程
  9. LDAP学习小结【仅原理和基础篇】
  10. 原创科幻短篇《Bug》