> 文章列表 > 项目9:会员列表的前后端联调

项目9:会员列表的前后端联调

项目9:会员列表的前后端联调

项目9:会员列表的前后端联调

1.会员列表的需求

2.会员列表后端开发

3.会员列表前端开发

4.锁定和解锁功能需求

5.后端锁定解锁开发

6.前端锁定解锁开发

7.登录日志需求

8.后端根据id查询登录日志

9.前端展示日志

项目9:会员列表的前后端联调

1.会员列表的需求

  • 展示会员列表数据
  • 根据条件查询会员列表
    项目9:会员列表的前后端联调
    项目9:会员列表的前后端联调

2.会员列表后端开发

①封装查询数据的实体类

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

②根据查询条件查询的controller

  • 注意
    前端传入的参数为UserInfoQuery,查询时查询的对象仍然为UserInfo
package com.atguigu.srb.core.controller.admin;import com.atguigu.common.result.R;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.query.UserInfoQuery;
import com.atguigu.srb.core.service.UserInfoService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;/*** <p>* 用户基本信息 前端控制器* </p>** @author Likejin* @since 2023-04-09*/
@Api(tags = "会员管理")
@RestController
@RequestMapping("/admin/core/userInfo")
@Slf4j
@CrossOrigin
public class AdminUserInfoController {@Resourceprivate UserInfoService userInfoService;@ApiOperation("获取会员分页列表")//get方法没有请求体,其他方式都可以有请求体,@GetMapping("/list/{page}/{limit}")public R listPage(@ApiParam(value = "当前页码")@PathVariable Long limit,@ApiParam(value = "每页记录")@PathVariable Long page,@ApiParam(value = "查询对象")UserInfoQuery userInfoQuery){Page<UserInfo> pageParam = new Page<>(page,limit);IPage<UserInfo> pageModel = userInfoService.listPage(pageParam,userInfoQuery);return R.ok().data("pageModel",pageModel);}}

③调用的service

package com.atguigu.srb.core.service;import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.query.UserInfoQuery;
import com.atguigu.srb.core.pojo.vo.LoginVO;
import com.atguigu.srb.core.pojo.vo.RegisterVO;
import com.atguigu.srb.core.pojo.vo.UserInfoVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;/*** <p>* 用户基本信息 服务类* </p>** @author Likejin* @since 2023-04-09*/
public interface UserInfoService extends IService<UserInfo> {void register(RegisterVO registerVO);UserInfoVO login(LoginVO loginVO, String ip);//查询分页信息IPage<UserInfo> listPage(Page<UserInfo> pageParam, UserInfoQuery userInfoQuery);}
package com.atguigu.srb.core.service.impl;import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.common.util.MD5;
import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.core.mapper.UserAccountMapper;
import com.atguigu.srb.core.mapper.UserInfoMapper;
import com.atguigu.srb.core.mapper.UserLoginRecordMapper;
import com.atguigu.srb.core.pojo.entity.UserAccount;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.entity.UserLoginRecord;
import com.atguigu.srb.core.pojo.query.UserInfoQuery;
import com.atguigu.srb.core.pojo.vo.LoginVO;
import com.atguigu.srb.core.pojo.vo.RegisterVO;
import com.atguigu.srb.core.pojo.vo.UserInfoVO;
import com.atguigu.srb.core.service.UserInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** <p>* 用户基本信息 服务实现类* </p>** @author Likejin* @since 2023-04-09*/
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {@Resourceprivate UserAccountMapper userAccountMapper;@Resourceprivate UserLoginRecordMapper userLoginRecordMapper;@Transactional(rollbackFor = Exception.class)@Overridepublic void register(RegisterVO registerVO) {//判断当前用户是否已经被注册QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();userInfoQueryWrapper.eq("mobile",registerVO.getMobile());//baseMapper被封装为UserInfoMapperInteger count = baseMapper.selectCount(userInfoQueryWrapper);Assert.isTrue(count==0, ResponseEnum.MOBILE_EXIST_ERROR);//插入用户信息记录 user_infoUserInfo 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(UserInfo.USER_AVATAR);baseMapper.insert(userInfo);//插入用户账户记录 user_accountUserAccount userAccount = new UserAccount();userAccount.setUserId(userInfo.getId());userAccountMapper.insert(userAccount);}/*** @param loginVO:* @param ip:* @return UserInfoVO* @author Likejin* @description 用户登录功能* @date 2023/4/13 16:17*/@Transactional(rollbackFor = Exception.class)@Overridepublic UserInfoVO login(LoginVO loginVO, String ip) {String mobile = loginVO.getMobile();String password = loginVO.getPassword();Integer userType = loginVO.getUserType();//用户名是否存在QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();userInfoQueryWrapper.eq("mobile",mobile).eq("User_type",userType);UserInfo userInfo = baseMapper.selectOne(userInfoQueryWrapper);Assert.notNull(userInfo,ResponseEnum.LOGIN_MOBILE_ERROR);//密码是否正确Assert.equals(MD5.encrypt(password),userInfo.getPassword(),ResponseEnum.LOGIN_PASSWORD_ERROR);//用户是否被禁用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.getPassword());//组装UserInfoVoUserInfoVO userInfoVO = new UserInfoVO();userInfoVO.setToken(token);userInfoVO.setName(userInfo.getName());userInfoVO.setNickName(userInfo.getNickName());userInfoVO.setHeadImg(userInfo.getHeadImg());userInfoVO.setMobile(userInfo.getMobile());userInfoVO.setUserType(userInfo.getUserType());return userInfoVO;}@Overridepublic IPage<UserInfo> listPage(Page<UserInfo> pageParam, UserInfoQuery userInfoQuery) {//可能不传参数if(userInfoQuery==null){return baseMapper.selectPage(pageParam,null);}String mobile = userInfoQuery.getMobile();Integer status = userInfoQuery.getStatus();Integer userType = userInfoQuery.getUserType();//如果只输入了某一个字段如何解决//eq方法提供第一个参数为true才封装QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();userInfoQueryWrapper.eq(StringUtils.isNotBlank(mobile),"mobile",mobile).eq(status!=null,"status",status).eq(userType!=null,"User_type",userType);//        if(StringUtils.isNotBlank(mobile)){
//            userInfoQueryWrapper.eq("mobile",mobile);
//        }
//        if(status!=null){
//            userInfoQueryWrapper.eq("status",status);
//        }
//        if(userType!=null){
//            userInfoQueryWrapper.eq("User_type",userType);
//        }return baseMapper.selectPage(pageParam,userInfoQueryWrapper);}
}

④时间格式的全局配置(针对localdatetime)

service-base包中

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;//仅用于localdatetime日期类型
@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;

3.会员列表前端开发

①增加路由

srb-admin\\src\\router\\index.js

 {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: '会员列表' },},],},

②创建引用的request

srb-admin\\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}`,//get形式传对象method: 'get',//用params,把参数的内容分散到url地址的?后面params: searchObj,//如果是post,且后台对应了@requestbody,则数据格式用data(在请求体中传递json)})},
}

③创建页面组件

srb-admin\\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="[1, 3, 10]"style="padding: 30px 0"layout="total, sizes, prev, pager, next, jumper"@size-change="changePageSize"@current-change="changeCurrentPage"/></div>
</template><script>
import userInfoApi from '@/api/core/user-info'export default {data() {return {list: null, // 数据列表total: 0, // 数据库中的总记录数page: 1, // 默认页码limit: 3, // 每页记录数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:回调参数,表示当前选中的“每页条数”,有默认的参数size为选中的page大小changePageSize(size) {this.limit = sizethis.fetchData()},// 改变页码,page:回调参数,表示当前选中的“页码”,有默认参数为page为选中的页码changeCurrentPage(page) {this.page = pagethis.fetchData()},// 重置表单resetData() {//还原表单this.searchObj = {}//重新查询this.fetchData()},},
}
</script>

4.锁定和解锁功能需求

  • 前后端传输数据
    前端传入id和status,后端根据id和status修改即可。

在这里插入图片描述
项目9:会员列表的前后端联调

5.后端锁定解锁开发

①controller层

package com.atguigu.srb.core.controller.admin;import com.atguigu.common.result.R;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.query.UserInfoQuery;
import com.atguigu.srb.core.service.UserInfoService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;/*** <p>* 用户基本信息 前端控制器* </p>** @author Likejin* @since 2023-04-09*/
@Api(tags = "会员管理")
@RestController
@RequestMapping("/admin/core/userInfo")
@Slf4j
@CrossOrigin
public class AdminUserInfoController {@Resourceprivate UserInfoService userInfoService;@ApiOperation("获取会员分页列表")//get方法没有请求体,其他方式都可以有请求体,@GetMapping("/list/{page}/{limit}")public R listPage(@ApiParam(value = "当前页码")@PathVariable Long limit,@ApiParam(value = "每页记录")@PathVariable Long page,@ApiParam(value = "查询对象")UserInfoQuery userInfoQuery){Page<UserInfo> pageParam = new Page<>(page,limit);IPage<UserInfo> pageModel = userInfoService.listPage(pageParam,userInfoQuery);return R.ok().data("pageModel",pageModel);}@ApiOperation("锁定和解锁")@PutMapping("/lock/{id}/{status}")public R lock(@ApiParam(value = "用户id")@PathVariable("id") Long id,@ApiParam(value = "锁定状态(0锁定 1 正常)")@PathVariable("status") Integer status){userInfoService.lock(id,status);return R.ok().message(status==1?"解锁成功":"锁定成功");}
}

②service层

package com.atguigu.srb.core.service;import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.query.UserInfoQuery;
import com.atguigu.srb.core.pojo.vo.LoginVO;
import com.atguigu.srb.core.pojo.vo.RegisterVO;
import com.atguigu.srb.core.pojo.vo.UserInfoVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;/*** <p>* 用户基本信息 服务类* </p>** @author Likejin* @since 2023-04-09*/
public interface UserInfoService extends IService<UserInfo> {void register(RegisterVO registerVO);UserInfoVO login(LoginVO loginVO, String ip);IPage<UserInfo> listPage(Page<UserInfo> pageParam, UserInfoQuery userInfoQuery);/*** @param id:* @param status:* @return void* @author Likejin* @description 根据用户id来更改用户状态* @date 2023/4/13 19:46*/void lock(Long id, Integer status);}
package com.atguigu.srb.core.service.impl;import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.common.util.MD5;
import com.atguigu.srb.base.util.JwtUtils;
import com.atguigu.srb.core.mapper.UserAccountMapper;
import com.atguigu.srb.core.mapper.UserInfoMapper;
import com.atguigu.srb.core.mapper.UserLoginRecordMapper;
import com.atguigu.srb.core.pojo.entity.UserAccount;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.entity.UserLoginRecord;
import com.atguigu.srb.core.pojo.query.UserInfoQuery;
import com.atguigu.srb.core.pojo.vo.LoginVO;
import com.atguigu.srb.core.pojo.vo.RegisterVO;
import com.atguigu.srb.core.pojo.vo.UserInfoVO;
import com.atguigu.srb.core.service.UserInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** <p>* 用户基本信息 服务实现类* </p>** @author Likejin* @since 2023-04-09*/
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {@Resourceprivate UserAccountMapper userAccountMapper;@Resourceprivate UserLoginRecordMapper userLoginRecordMapper;@Transactional(rollbackFor = Exception.class)@Overridepublic void register(RegisterVO registerVO) {//判断当前用户是否已经被注册QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();userInfoQueryWrapper.eq("mobile",registerVO.getMobile());//baseMapper被封装为UserInfoMapperInteger count = baseMapper.selectCount(userInfoQueryWrapper);Assert.isTrue(count==0, ResponseEnum.MOBILE_EXIST_ERROR);//插入用户信息记录 user_infoUserInfo 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(UserInfo.USER_AVATAR);baseMapper.insert(userInfo);//插入用户账户记录 user_accountUserAccount userAccount = new UserAccount();userAccount.setUserId(userInfo.getId());userAccountMapper.insert(userAccount);}/*** @param loginVO:* @param ip:* @return UserInfoVO* @author Likejin* @description 用户登录功能* @date 2023/4/13 16:17*/@Transactional(rollbackFor = Exception.class)@Overridepublic UserInfoVO login(LoginVO loginVO, String ip) {String mobile = loginVO.getMobile();String password = loginVO.getPassword();Integer userType = loginVO.getUserType();//用户名是否存在QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();userInfoQueryWrapper.eq("mobile",mobile).eq("User_type",userType);UserInfo userInfo = baseMapper.selectOne(userInfoQueryWrapper);Assert.notNull(userInfo,ResponseEnum.LOGIN_MOBILE_ERROR);//密码是否正确Assert.equals(MD5.encrypt(password),userInfo.getPassword(),ResponseEnum.LOGIN_PASSWORD_ERROR);//用户是否被禁用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.getPassword());//组装UserInfoVoUserInfoVO userInfoVO = new UserInfoVO();userInfoVO.setToken(token);userInfoVO.setName(userInfo.getName());userInfoVO.setNickName(userInfo.getNickName());userInfoVO.setHeadImg(userInfo.getHeadImg());userInfoVO.setMobile(userInfo.getMobile());userInfoVO.setUserType(userInfo.getUserType());return userInfoVO;}@Overridepublic IPage<UserInfo> listPage(Page<UserInfo> pageParam, UserInfoQuery userInfoQuery) {//可能不传参数if(userInfoQuery==null){return baseMapper.selectPage(pageParam,null);}String mobile = userInfoQuery.getMobile();Integer status = userInfoQuery.getStatus();Integer userType = userInfoQuery.getUserType();//如果只输入了某一个字段如何解决//eq方法提供第一个参数为true才封装QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();userInfoQueryWrapper.eq(StringUtils.isNotBlank(mobile),"mobile",mobile).eq(status!=null,"status",status).eq(userType!=null,"User_type",userType);//        if(StringUtils.isNotBlank(mobile)){
//            userInfoQueryWrapper.eq("mobile",mobile);
//        }
//        if(status!=null){
//            userInfoQueryWrapper.eq("status",status);
//        }
//        if(userType!=null){
//            userInfoQueryWrapper.eq("User_type",userType);
//        }return baseMapper.selectPage(pageParam,userInfoQueryWrapper);}/*** @param id:* @param status:* @return void* @author Likejin* @description 根据id修改状态* @date 2023/4/13 19:46*/@Overridepublic void lock(Long id, Integer status) {UserInfo userInfo = new UserInfo();userInfo.setId(id);userInfo.setStatus(status);baseMapper.updateById(userInfo);}
}

6.前端锁定解锁开发

①增加方法

  • request传参id和status
    srb-admin\\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}`,//get形式传对象method: 'get',//用params,把参数的内容分散到url地址的?后面params: searchObj,//如果是post,且后台对应了@requestbody,则数据格式用data(在请求体中传递json)})},lock(id, status) {return request({url: `/admin/core/userInfo/lock/${id}/${status}`,method: 'put',})},
}

②页面组件

srb-admin\\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></el-table>
//加在methods方法中// 锁定和解锁lock(id, status) {userInfoApi.lock(id, status).then(response => {this.$message.success(response.message)this.fetchData()})}

7.登录日志需求

  • 前端传入id,后端根据id查询登录日志
  • 数据库
    日志对象

项目9:会员列表的前后端联调
项目9:会员列表的前后端联调
项目9:会员列表的前后端联调

8.后端根据id查询登录日志

①controller

package com.atguigu.srb.core.controller.admin;import com.atguigu.common.result.R;
import com.atguigu.srb.core.pojo.entity.UserLoginRecord;
import com.atguigu.srb.core.service.UserLoginRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.List;/*** <p>* 用户登录记录表 前端控制器* </p>** @author Likejin* @since 2023-04-09*/
@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")@PathVariable Long userId){List<UserLoginRecord> userLoginRecords =  userLoginRecordService.listTop50(userId);return R.ok().data("list",userLoginRecords);}}

②查询service

package com.atguigu.srb.core.service;import com.atguigu.srb.core.pojo.entity.UserLoginRecord;
import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;/*** <p>* 用户登录记录表 服务类* </p>** @author Likejin* @since 2023-04-09*/
public interface UserLoginRecordService extends IService<UserLoginRecord> {List<UserLoginRecord> listTop50(Long userId);}
package com.atguigu.srb.core.service.impl;import com.atguigu.srb.core.pojo.entity.UserLoginRecord;
import com.atguigu.srb.core.mapper.UserLoginRecordMapper;
import com.atguigu.srb.core.service.UserLoginRecordService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;import java.util.List;/*** <p>* 用户登录记录表 服务实现类* </p>** @author Likejin* @since 2023-04-09*/
@Service
public class UserLoginRecordServiceImpl extends ServiceImpl<UserLoginRecordMapper, UserLoginRecord> implements UserLoginRecordService {@Overridepublic 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;}
}

9.前端展示日志

①前端封装方法

srb-admin\\src\\api\\core\\user-info.js

  //获取登录日志getuserLoginRecordTop50(userId) {return request({url: `/admin/core/userLoginRecord/listTop50/${userId}`,method: 'get',})},

②前端增加页面组件

srb-admin\\src\\views\\core\\user-info\\list.vue

//放在方法中// 根据id查询会员日志记录showLoginRecord(id) {//打开对话框this.dialogTableVisible = true//加载数据列表userInfoApi.getuserLoginRecordTop50(id).then((response) => {this.loginRecordList = response.data.list})},
<!--放在table为操作中--><el-buttontype="primary"size="mini"@click="showLoginRecord(scope.row.id)">登录日志</el-button>
<!--放在/div前--><!-- 用户登录日志 --><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>

未更新

未更新

未更新

未更新

未更新