【金融项目】尚融宝项目(七)
13、用戶注冊
13.1、前端整合發(fā)送短信驗(yàn)證碼
13.1.1、運(yùn)行srb-site
13.1.1.1、解壓
srb_site
13.1.1.2、運(yùn)行
npm run dev13.1.2、前端頁面整合
pages/register.vue
methods: {//發(fā)短信 send() {if (!this.userInfo.mobile) {this.$message.error('請輸入手機(jī)號')return}//防止重復(fù)提交if (this.sending) returnthis.sending = true//倒計(jì)時(shí)this.timeDown()//遠(yuǎn)程調(diào)用發(fā)送短信的接口this.$axios.$get('/api/sms/send/' + this.userInfo.mobile).then((response) => {this.$message.success(response.message)})},//倒計(jì)時(shí)timeDown() {console.log('進(jìn)入倒計(jì)時(shí)')this.leftSecond = this.second//創(chuàng)建定時(shí)器const timmer = setInterval(() => {//計(jì)數(shù)器減一this.leftSecond--if (this.leftSecond <= 0) {//停止定時(shí)器clearInterval(timmer)//還原計(jì)數(shù)器this.leftSecond = this.second//還原按鈕狀態(tài)this.sending = false}}, 1000)},},13.2、實(shí)現(xiàn)用戶注冊
13.2.1、需求
13.2.2、后端接口
13.2.2.1、創(chuàng)建VO對象
service-core中創(chuàng)建vo
package com.atguigu.srb.core.pojo.vo; @Data @ApiModel(description="注冊對象") public class RegisterVO {@ApiModelProperty(value = "用戶類型")private Integer userType;@ApiModelProperty(value = "手機(jī)號")private String mobile;@ApiModelProperty(value = "驗(yàn)證碼")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 = "會(huì)員接口") @RestController @RequestMapping("/api/core/userInfo") @Slf4j @CrossOrigin public class UserInfoController {@Resourceprivate UserInfoService userInfoService;@Resourceprivate RedisTemplate redisTemplate;@ApiOperation("會(huì)員注冊")@PostMapping("/register")public R register(@RequestBody RegisterVO registerVO){String mobile = registerVO.getMobile();String password = registerVO.getPassword();String code = registerVO.getCode();//MOBILE_NULL_ERROR(-202, "手機(jī)號不能為空"),Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);//MOBILE_ERROR(-203, "手機(jī)號不正確"),Assert.isTrue(RegexValidateUtils.checkCellphone(mobile), ResponseEnum.MOBILE_ERROR);//PASSWORD_NULL_ERROR(-204, "密碼不能為空"),Assert.notEmpty(password, ResponseEnum.PASSWORD_NULL_ERROR);//CODE_NULL_ERROR(-205, "驗(yàn)證碼不能為空"),Assert.notEmpty(code, ResponseEnum.CODE_NULL_ERROR);//校驗(yàn)驗(yàn)證碼String codeGen = (String)redisTemplate.opsForValue().get("srb:sms:code:" + mobile);//CODE_ERROR(-206, "驗(yàn)證碼不正確"),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); }實(shí)現(xiàn):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, "手機(jī)號已被注冊"),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); //正常//設(shè)置一張靜態(tài)資源服務(wù)器上的頭像圖片userInfo.setHeadImg("https://srb-file.oss-cn-beijing.aliyuncs.com/avatar/07.jpg");baseMapper.insert(userInfo);//創(chuàng)建會(huì)員賬戶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、用戶認(rèn)證
14.1、實(shí)現(xiàn)用戶登錄
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、創(chuàng)建VO對象
service-core中創(chuàng)建登錄對象
package com.atguigu.srb.core.pojo.vo;@Data @ApiModel(description="登錄對象") public class LoginVO {@ApiModelProperty(value = "用戶類型")private Integer userType;@ApiModelProperty(value = "手機(jī)號")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 = "手機(jī)號")private String mobile;@ApiModelProperty(value = "1:出借人 2:借款人")private Integer userType;@ApiModelProperty(value = "JWT訪問令牌")private String token; }14.1.2.4、Controller
UserInfoController
@ApiOperation("會(huì)員登錄") @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);實(shí)現(xiàn):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();//獲取會(huì)員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);//校驗(yàn)密碼//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', '')//跳轉(zhuǎn)頁面window.location.href = '/login'},}, } </script>14.2、校驗(yàn)用戶登錄
14.2.1、后端的接口
14.2.1.1、添加令牌校驗(yàn)接口
service-core 中 UserInfoController添加令牌校驗(yàn)接口
@ApiOperation("校驗(yàn)令牌") @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:添加全局參數(shù)
step4:測試
14.2.2、前端整合
14.2.2.1、優(yōu)化showInfo
components/AppHeader.vue
腳本
showInfo() {// debuggerlet userInfo = cookie.get('userInfo')if (!userInfo) {console.log('cookie不存在')this.userInfo = nullreturn}userInfo = JSON.parse(userInfo)//先在服務(wù)器端校驗(yàn)tokenthis.$axios({url: '/api/core/userInfo/checkToken',method: 'get',headers: {//如果token校驗(yàn)成功,再展示user信息token: userInfo.token,},}).then((response) => {console.log('校驗(yàn)成功')this.userInfo = userInfo}) },14.2.2.2、axios請求攔截(了解)
可以在axios請求攔截器中統(tǒng)一添加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響應(yīng)攔截(了解)
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校驗(yàn)失敗')cookie.set('userInfo', '')//debugger//跳轉(zhuǎn)到登錄頁面window.location.href = '/login'} else {Message({message: response.data.message,type: 'error',duration: 5 * 1000,})return Promise.reject(response)}})15、會(huì)員管理
15.1、會(huì)員分頁列表
15.1.1、需求
15.1.2、后端接口實(shí)現(xiàn)
15.1.2.1、創(chuàng)建查詢對象
UserInfoQuery
package com.atguigu.srb.core.pojo.query;@Data @ApiModel(description="會(huì)員搜索對象") public class UserInfoQuery {@ApiModelProperty(value = "手機(jī)號")private String mobile;@ApiModelProperty(value = "狀態(tài)")private Integer status;@ApiModelProperty(value = "1:出借人 2:借款人")private Integer userType; }15.1.2.2、Service
接口:UserInfoService
IPage<UserInfo> listPage(Page<UserInfo> pageParam, UserInfoQuery userInfoQuery);實(shí)現(xiàn):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 = "會(huì)員管理") @RestController @RequestMapping("/admin/core/userInfo") @Slf4j @CrossOrigin public class AdminUserInfoController {@Resourceprivate UserInfoService userInfoService;@ApiOperation("獲取會(huì)員分頁列表")@GetMapping("/list/{page}/{limit}")public R listPage(@ApiParam(value = "當(dāng)前頁碼", required = true)@PathVariable Long page,@ApiParam(value = "每頁記錄數(shù)", 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());} }上面的方案全局生效,當(dāng)全局的格式化方式無法滿足我們需求時(shí),我們對日期格式要做特殊的處理:在類的屬性上添加注解
@JsonFormat(pattern = "yyyy-MM-dd") @ApiModelProperty(value = "創(chuàng)建時(shí)間") private LocalDateTime createTime;15.1.3、前端整合
15.1.3.1、創(chuàng)建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: '會(huì)員管理', icon: 'user' },alwaysShow: true,children: [{path: 'list',name: 'coreUserInfoList',component: () => import('@/views/core/user-info/list'),meta: { title: '會(huì)員列表' }}]},15.1.3.3、定義api模塊
創(chuàng)建文件 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, // 數(shù)據(jù)列表total: 0, // 數(shù)據(jù)庫中的總記錄數(shù)page: 1, // 默認(rèn)頁碼limit: 10, // 每頁記錄數(shù)searchObj: {}, // 查詢條件loginRecordList: [], //會(huì)員登錄日志dialogTableVisible: false //對話框是否顯示}},created() {// 當(dāng)頁面加載時(shí)獲取數(shù)據(jù)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})},// 每頁記錄數(shù)改變,size:回調(diào)參數(shù),表示當(dāng)前選中的“每頁條數(shù)”changePageSize(size) {this.limit = sizethis.fetchData()},// 改變頁碼,page:回調(diào)參數(shù),表示當(dāng)前選中的“頁碼”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="手機(jī)號"><el-input v-model="searchObj.mobile" placeholder="手機(jī)號" /></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="用戶狀態(tài)"><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="手機(jī)號" /><el-table-column prop="name" label="用戶姓名" /><el-table-column prop="idCard" label="身份證號" /><el-table-column prop="integral" label="用戶積分" /><el-table-column prop="createTime" label="注冊時(shí)間" width="100" /><el-table-column label="綁定狀態(tài)" 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="用戶狀態(tài)" 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**、后端接口實(shí)現(xiàn)**
15.2.1.1、Service
接口:UserInfoService
void lock(Long id, Integer status);實(shí)現(xiàn):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 = "鎖定狀態(tài)(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、后端接口實(shí)現(xiàn)
15.3.1.1、Controller
AdminUserLoginRecordController
package com.atguigu.srb.core.controller.admin;@Api(tags = "會(huì)員登錄日志接口") @RestController @RequestMapping("/admin/core/userLoginRecord") @Slf4j @CrossOrigin public class AdminUserLoginRecordController {@Resourceprivate UserLoginRecordService userLoginRecordService;@ApiOperation("獲取會(huì)員登錄日志列表")@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);實(shí)現(xiàn):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、定義頁面組件腳本
// 根據(jù)id查詢會(huì)員日志記錄showLoginRecord(id) {//打開對話框this.dialogTableVisible = true//加載數(shù)據(jù)列表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="登錄時(shí)間" /></el-table> </el-dialog>本文章參考B站 尚硅谷《尚融寶》Java微服務(wù)分布式金融項(xiàng)目,僅供個(gè)人學(xué)習(xí)使用,部分內(nèi)容為本人自己見解,與尚硅谷無關(guān)。
總結(jié)
以上是生活随笔為你收集整理的【金融项目】尚融宝项目(七)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 博客中 Flex4/Flash mp3音
- 下一篇: 极米H5多少流明?采用新亮度标准的极米H