SpringBoot+SpringSecurity+MybatisPlus+Vue3小项目摘录(九)

2024-01-03 12:29:26

文章目录

用户信息管理模块化操作

1、用户信息列表分页显示数据实现

提示:这里参考MybatisPlus的分页处理【参考官网】https://baomidou.com/pages/97710a/

在这里插入图片描述

可以在实体对象中封装一个分页的对象
package com.xuguoguo.entity;

/**
 * 分页Model类
 * @author xuguoguo
 * @create 2023-11-16 上午 11:05
 */
public class PageBean {


    private int pageNum; // 第几页
    private int pageSize; // 每页记录数
    private int start;  // 起始页
    private String query; // 查询参数

    public PageBean() {
    }

    public PageBean(int pageNum, int pageSize, String query) {
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.query = query;
    }

    public PageBean(int pageNum, int pageSize) {
        super();
        this.pageNum = pageNum;
        this.pageSize = pageSize;
    }

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getStart() {
        return (pageNum-1)*pageSize;
    }

    public String getQuery() {
        return query;
    }

    public void setQuery(String query) {
        this.query = query;
    }
}

后端控制器的编写如下:
请求方法上需要加上权限的处理哦

在这里插入图片描述


/**
 * 根据条件分页查询用户信息
 * @param pageBean
 * @return
 */
@PostMapping("/list")
@PreAuthorize("hasAuthority('system:user:query')")
public ResponseData list(@RequestBody PageBean pageBean){
    Page<SysUser> pageResult = sysUserService.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()));
    List<SysUser> userList = pageResult.getRecords();
    Map<String,Object> resultMap=new HashMap<>();
    resultMap.put("userList",userList);
    resultMap.put("total",pageResult.getTotal());
    return new ResponseData("请求成功!",200,resultMap);
}

前端的views/sys/user/index.vue组件的编写
<template>
  <div class="app-container">

    <el-table :data="tableData" stripe style="width: 100%">
      <el-table-column prop="id" label="用户ID"  sortable align="center"/>
        <el-table-column prop="avatar" label="头像" align="center">
          <template v-slot="scope">
            <img :src="getServerUrl()+'image/userAvatar/'+scope.row.avatar"  height="50"/>
          </template>
        </el-table-column>
        <el-table-column prop="username" label="用户名"   align="center"/>
        <el-table-column prop="email" label="邮箱"  align="center"/>
        <el-table-column prop="phonenumber" label="手机号"  align="center"/>
        <el-table-column prop="createTime" label="创建时间" sortable align="center"/>
        <el-table-column prop="loginDate" label="最后登录时间" sortable  align="center"/>
        <el-table-column prop="remark" label="备注"  />
    </el-table>
    
    <!-- 分页开始 -->
    <el-pagination
          v-model:current-page="queryForm.pageNum"
          v-model:page-size="queryForm.pageSize"
          :page-sizes="[5, 10, 15, 20]"
          :small="small"
          :disabled="disabled"
          :background="background"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />

  </div>
</template>

<script setup>
import {ref} from 'vue';
import requestUtil,{getServerUrl} from "@/util/request";

const tableData=ref([]);

const total=ref(0);

const queryForm=ref({
  query:'',
  pageNum:1,
  pageSize:5
})

const initUserList=async()=>{
  const res=await requestUtil.post("sys/user/list",queryForm.value);
  tableData.value=res.data.data.userList;
  total.value=res.data.data.total;
}

initUserList();

const handleSizeChange=(pageSize)=>{
  queryForm.value.pageNum=1;
  queryForm.value.pageSize=pageSize;
  initUserList();
}

const handleCurrentChange=(pageNum)=>{
  queryForm.value.pageNum=pageNum;
  initUserList();
}




</script>

<style lang="scss" scoped>

.header{
  padding-bottom: 16px;
  box-sizing: border-box;
}

.el-pagination{
  float: right;
  padding: 20px;
  box-sizing: border-box;
}

::v-deep th.el-table__cell{
  word-break: break-word;
  background-color: #f8f8f9 !important;
  color: #515a6e;
  height: 40px;
  font-size: 13px;

}

.el-tag--small {
  margin-left: 5px;
}
</style>

预览效果:

在这里插入图片描述

国际化处理
在main.js中进行处理即可

在这里插入图片描述
在这里插入图片描述

常见问题

在这里插入图片描述

如果在请求的过程中,出现上述问题,则需要检查你的vue页面中定义的数据的类型是否与后端响应回来的数据进行匹配。

一般情况下,检查数据定义的类型即可解决好!~~~

如下:

在这里插入图片描述

需改成:

在这里插入图片描述

用户搜索功能

1、添加搜索的组件【sys/user/index.vue】

在这里插入图片描述

2、引入图标和进行属性声明

在这里插入图片描述

3、预览效果

在这里插入图片描述

4、后端的实现
  • 修改用户对象中的属性【因为页面中需要显示每个用户拥有的角色名称】
    在这里插入图片描述

  • 控制器的改写
    在这里插入图片描述

前端渲染的表格中全部显示列的值【有些列需要进行格式化处理】

在这里插入图片描述

预览效果:

在这里插入图片描述

搜索框输入xu

在这里插入图片描述

添加/修改用户信息的功能

在这里插入图片描述
在这里插入图片描述

无论是用户的新增还是修改都是通过组件对话框dialog实现的,之前我们是直接在本页面中写,
此次改写一个,通过拆分子组件去编写对话框组件实现用户的新增/修改。

在sys/user目录下新建components目录并新建组件dialog.vue

在这里插入图片描述

注意事项
1、这里需要一点时间去处理表单数据以及验证和事件的处理哦!!!
2、子父组件的通信【属性和事件】

这里直接贴出dialog.vue的代码仅供参考
<template>

  <el-dialog
    v-model="dialogVisible"
    :title="dialogTitle"
    width="30%"
    @close="handleClose"
  >
       <el-form
        ref="formRef"
        :model="form"
        :rules="rules"
        label-width="100px"
    >
      <el-form-item label="用户名" prop="username">
        <el-input v-model="form.username" :disabled="form.id==-1?false:'disabled'"  />
        <el-alert
            v-if="form.id==-1"
            title="默认初始密码:123456"
            :closable="false"
            style="line-height: 10px;"
            type="success" >
        </el-alert>
      </el-form-item>

      <el-form-item label="手机号" prop="phonenumber">
        <el-input v-model="form.phonenumber" />
      </el-form-item>

      <el-form-item label="邮箱" prop="email">
        <el-input v-model="form.email" />
      </el-form-item>

      <el-form-item label="状态" prop="status">
        <el-radio-group v-model="form.status">
          <el-radio :label="'0'">正常</el-radio>
          <el-radio :label="'1'">禁用</el-radio>
        </el-radio-group>
      </el-form-item>


      <el-form-item label="备注" prop="remark">
        <el-input v-model="form.remark" type="textarea" :rows="4"/>
      </el-form-item>


    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" @click="handleConfirm">确认</el-button>
        <el-button @click="handleClose"
          >取消</el-button
        >
      </span>
    </template>
  </el-dialog>

</template>

<script setup>
import {defineEmits, defineProps,ref,watch } from "vue"
import requestUtil,{getServerUrl} from "@/util/request";
import { ElMessage } from 'element-plus'

const props=defineProps(
    {
      id:{
        type:Number,
        default:-1,
        required:true
      },
      dialogTitle:{
        type:String,
        default:'',
        required:true
      },
      dialogVisible:{
        type:Boolean,
        default:false,
        required:true
      }
    }
)

const dialogVisible=ref(false);


const form=ref({
  id:-1,
  username:"",
  password:"123456",
  status:"0",
  phonenumber:"",
  email:"",
  remark:""
})

const checkUsername = async (rule, value, callback) => {
  if(form.value.id==-1){
    const res=await requestUtil.post("sys/user/checkUserName",{username:form.value.username});
    if (res.data.code==500) {
      callback(new Error("用户名已存在!"));
    } else {
      callback();
    }
  }else{
    callback();
  }

}


const rules=ref({
  username:[
    { required: true, message: '请输入用户名'},
    { required: true, validator: checkUsername, trigger: "blur" }
  ],
  email: [{ required: true, message: "邮箱地址不能为空", trigger: "blur" }, { type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
  phonenumber: [{ required: true, message: "手机号码不能为空", trigger: "blur" }, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }],
})

const formRef=ref(null)

const initFormData=async(id)=>{
  const res=await requestUtil.get("sys/user/"+id);
  console.log("根据id查询的值:");
  console.log(res);
  form.value=res.data.data.sysUser;
}

watch(
    ()=>props.dialogVisible,
    ()=>{
      let id=props.id;
      console.log("id="+id)
      if(id!=-1){
        initFormData(id);
      }else{
        form.value={
          id:-1,
          username:"",
          password:"123456",
          status:"0",
          phonenumber:"",
          email:"",
          remark:""
        }
      }
    }
)

const emits=defineEmits(['update:modelValue','initUserList'])

const handleClose=()=>{
  emits('update:modelValue',false)
}

const handleConfirm=()=>{
  formRef.value.validate(async(valid)=>{
    if(valid){
      let result=await requestUtil.post("sys/user/save",form.value);
      let data=result.data;
      if(data.code==200){
        ElMessage.success("执行成功!")
        formRef.value.resetFields();
        //调用父组件刷新数据
        emits("initUserList")
        handleClose();
      }else{
        ElMessage.error(data.msg);
      }
    }else{
      console.log("fail")
    }
  })
}

</script>

<style lang="scss" scoped>

</style>
在user/index.vue中需要进行引入组件处理

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

点击确认实现新增/修改

在这里插入图片描述在这里插入图片描述

后端的控制器中的方法编写

在这里插入图片描述

表单校验用户名不能重复的实现

在这里插入图片描述

后端的请求方法编写:

在这里插入图片描述

更新的操作
1、点击表格中行里的编辑按钮触发事件【根据id查询用户信息回显到表单中】

在这里插入图片描述
在这里插入图片描述

2、进行修改提交操作【共用】

在这里插入图片描述

后台控制器的几个相关请求方法代码如下:
/**
 * 添加或者修改
 * @param sysUser
 * @return
 */
@PostMapping("/save")
@PreAuthorize("hasAuthority('system:user:add')"+"||"+"hasAuthority('system:user:edit')")
public ResponseData save(@RequestBody SysUser sysUser){
    if(sysUser.getId()==null || sysUser.getId()==-1){
        sysUser.setCreateTime(new Date());
        sysUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getPassword()));
        sysUser.setId(null);//自增
        sysUserService.save(sysUser);
    }else{
        sysUser.setUpdateTime(new Date());
        sysUserService.updateById(sysUser);
    }
    return new ResponseData("操作成功",200);
}

/**
 * 根据id查询
 * @param id
 * @return
 */
@GetMapping("/{id}")
@PreAuthorize("hasAuthority('system:user:query')")
public ResponseData findById(@PathVariable(value = "id")Integer id){
    SysUser sysUser = sysUserService.getById(id);
    Map<String,Object> map=new HashMap<>();
    map.put("sysUser",sysUser);
    return new ResponseData(map);
}

/**
 * 验证用户名
 * @param sysUser
 * @return
 */
@PostMapping("/checkUserName")
@PreAuthorize("hasAuthority('system:user:query')")
public ResponseData checkUserName(@RequestBody SysUser sysUser){
    if(sysUserService.getByUsername(sysUser.getUsername())==null){
        return new ResponseData("可以使用!",200);
    }else{
        return new ResponseData("用户名已存在!",500);
    }
}

删除和批量删除用户信息

以往我们都是单个删除一个请求,批量删除一个请求,这样其实可以简化,直接简化成一个方法即可!!!

后端的删除请求方法:

在这里插入图片描述

前端的控制处理
1、顶部的工具条位置

在这里插入图片描述在这里插入图片描述

预览效果[没没有选择复选框的时候delBtnStatus变量的值为true,则为禁用,必须选择了才能点击

在这里插入图片描述
在这里插入图片描述

2、每行中的单个删除

在这里插入图片描述
在这里插入图片描述

用户管理【信息密码重置和用户状态的更新】

重置用户的密码
后端控制器方法的编写:

在这里插入图片描述

编写常量类/枚举存放定值

在这里插入图片描述

前端的处理

在这里插入图片描述在这里插入图片描述

测试重置密码
重置id为5的用户密码

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述

用户状态的更新
后端的请求方法编写

在这里插入图片描述

前端的组件事件处理:

查看文档https://element-plus.gitee.io/zh-CN/component/switch.html#attributes

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

事件处理实现

在这里插入图片描述

预览效果实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

用户分配角色功能实现

点击分配角色的按钮弹出对话框进行角色的分配实现

在这里插入图片描述

在user/components目录下新建roleDialog.vue组件

在这里插入图片描述

组件代码可以参考dialog.vue中的内容进行修改即可
<template>
  <el-dialog
    model-value="roleDialogVisible"
    title="分配角色"
    width="30%"
    @close="handleClose"
  >

    <el-form
        ref="formRef"
        :model="form"
        label-width="100px"
    >

      <el-checkbox-group v-model="form.checkedRoles">
        <el-checkbox v-for="role in form.roleList" :id="role.id" :key="role.id" :label="role.id"  name="checkedRoles" >{{role.name}}</el-checkbox>
      </el-checkbox-group>

    </el-form>

    <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" @click="handleConfirm">确认</el-button>
        <el-button  @click="handleClose">取消</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>

import {defineEmits, defineProps, ref, watch} from "vue";
import requestUtil,{getServerUrl} from "@/util/request";
import { ElMessage } from 'element-plus'


  const props=defineProps(
      {
        id:{
          type:Number,
          default:-1,
          required:true
        },
        roleDialogVisible:{
          type:Boolean,
          default:false,
          required:true
        },
        sysRoleList:{
          type:Array,
          default:[],
          required:true
        }
      }
  )


const form=ref({
  id:-1,
  roleList:[],
  checkedRoles:[]
})


const formRef=ref(null)

const initFormData=async(id)=>{
  const res=await requestUtil.get("sys/role/listAll");
  form.value.roleList=res.data.data.roleList;
  form.value.id=id;
}


  watch(
      ()=>props.roleDialogVisible,
      ()=>{
        let id=props.id;
        console.log("id="+id);
        if(id!=-1){
          form.value.checkedRoles=[]
          props.sysRoleList.forEach(item=>{
            form.value.checkedRoles.push(item.id);
          })
          initFormData(id);
        }
      }
  )


  const emits=defineEmits(['update:modelValue','initUserList']);

  const handleClose=()=>{
    emits('update:modelValue',false);
  }

  const handleConfirm=()=>{
    formRef.value.validate(async(valid)=>{
      if(valid){
          let result=await requestUtil.post("sys/user/grantRole/"+form.value.id,form.value.checkedRoles);
          let data=result.data;
          if(data.code==200){
            ElMessage.success("执行成功!")

            emits("initUserList");
            handleClose();
          }else{
            ElMessage.error(data.msg);
          }
      }else{
        console.log("fail");
      }
    })
  }

</script>

<style scoped>

</style>

在index.vue组件中进行引入并使用

在这里插入图片描述

在分配角色上添加事件

在这里插入图片描述在这里插入图片描述

复选框组件的文档可以参考文档来编写

https://element-plus.gitee.io/zh-CN/component/checkbox.html#checkbox-attributes
在这里插入图片描述在这里插入图片描述

后端新建角色的控制器实现查询所有的角色信息

在这里插入图片描述

预览效果:

在这里插入图片描述

点击确认,修改用户关联的角色信息【先将当前用户关联的角色删除,再更新分配的新角色】

在这里插入图片描述在这里插入图片描述

后端的控制器实现分配角色信息

在这里插入图片描述

效果测试:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述分配完毕重新查看!!!

在这里插入图片描述

代码规整
前端方面

在这里插入图片描述

index.vue代码如下:
<template>
  <div class="app-container">
    <!-- 功能按钮 -->
    <div style="margin:10px;">
      <el-button type="success" :icon="DocumentAdd" @click="handleDialogValue()">新增</el-button>
      <el-popconfirm title="您确定批量删除这些记录吗?" @confirm="handleDelete(null)">
        <template #reference>
         <el-button type="danger" :disabled="delBtnStatus" :icon="Delete" >批量删除</el-button>
        </template>
       </el-popconfirm>
    </div>
      <!-- 搜索框  :gutter为调整间距 -->
    <el-row :gutter="20" class="header">
        <el-col :span="7">
          <el-input placeholder="请输入用户名..." v-model="queryForm.query" clearable ></el-input>
        </el-col>
        <el-button type="primary" :icon="Search" @click="initUserList">搜索</el-button>
    </el-row>
    <!-- 渲染用户信息列表 -->
    <el-table :data="tableData" stripe style="width: 100%" @selection-change="handleSelectionChange">
      <!-- 复选框 -->
      <el-table-column type="selection" width="50" />
      <el-table-column prop="id" label="ID" width="50"  sortable align="center"/>
        <el-table-column prop="avatar" label="头像" align="center">
          <template v-slot="scope">
            <img :src="getServerUrl()+'image/userAvatar/'+scope.row.avatar"  height="50"/>
          </template>
        </el-table-column>
        <el-table-column prop="username" label="用户名"  width="100"  align="center"/>
        <el-table-column prop="roles" label="拥有角色" width="160" align="center">
          <template v-slot="scope">
            <el-tag size="small" type="warning" v-for="item in scope.row.sysRoleList" :key="item.id">   {{item.name}}</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="email" label="邮箱" width="200"  align="center"/>
        <el-table-column prop="phonenumber" label="手机号" width="150"  align="center"/>
        <el-table-column prop="status" label="用户状态" width="200" align="center" >
          <template v-slot="{row}" >
            <el-switch  v-model="row.status" @change="statusChangeHandle(row)" active-text="正常"
                        inactive-text="禁用" active-value="0" inactive-value="1"></el-switch>
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="创建时间" width="160" sortable align="center"/>
        <el-table-column prop="loginDate" label="最后登录时间" width="160" sortable  align="center"/>
        <el-table-column prop="remark" label="备注"  />
        <el-table-column prop="action" label="操作" width="400" fixed="right" align="center">
          <template v-slot="scope" >
            <el-button  type="primary" :icon="Tools" @click="handleRoleDialogValue(scope.row.id,scope.row.sysRoleList)" >分配角色</el-button>
            <!-- 如果用户名是管理员,则不能修改 -->
            <el-button v-if="scope.row.username!='xuguoguo'" type="primary" :icon="Edit" 
               @click="handleDialogValue(scope.row.id)" />
            <el-popconfirm  v-if="scope.row.username!='xuguoguo'" title="您确定要删除这条记录吗?" @confirm="handleDelete(scope.row.id)">
              <template #reference>
                <el-button  type="danger" :icon="Delete" />
              </template>
            </el-popconfirm>
            <el-popconfirm  v-if="scope.row.username!='xuguoguo'" title="您确定要对这个用户重置密码吗?" @confirm="handleResetPassword(scope.row.id)">
              <template #reference>
                <el-button  type="warning" :icon="RefreshRight" >重置密码</el-button>
              </template>
          </el-popconfirm>
          </template>    
      </el-table-column>
    </el-table>
    
    <!-- 分页开始 -->
    <el-pagination
          v-model:current-page="queryForm.pageNum"
          v-model:page-size="queryForm.pageSize"
          :page-sizes="[5, 10, 15, 20]"
          :small="small"
          :disabled="disabled"
          :background="background"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />

  </div>

  <!-- 定义dialog对话框 -->
  <Dialog v-model="dialogVisible" :dialogVisible="dialogVisible" :id="id" :dialogTitle="dialogTitle" @initUserList="initUserList"/>

  <!-- 显示角色的对话框 -->
  <RoleDialog v-model="roleDialogVisible" :sysRoleList="sysRoleList" :roleDialogVisible="roleDialogVisible"
   :id="id" @initUserList="initUserList"></RoleDialog>

</template>

<script setup>
import {ref} from 'vue';
import requestUtil,{getServerUrl} from "@/util/request";
import { Search ,Delete,DocumentAdd ,Edit, Tools, RefreshRight} from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'

import Dialog from './components/dialog'
import RoleDialog from './components/roleDialog'

const sysRoleList=ref([]);

const roleDialogVisible=ref(false);


const dialogVisible=ref(false);

const dialogTitle=ref("");

const id=ref(-1);

const delBtnStatus=ref(true);

const multipleSelection=ref([]);

const handleRoleDialogValue=(userId,roleList)=>{
  console.log("userId="+userId)
  id.value=userId;
  sysRoleList.value=roleList;
  roleDialogVisible.value=true;
}

const statusChangeHandle=async (row)=>{
  let res=await requestUtil.get("sys/user/updateStatus/"+row.id+"/status/"+row.status);
  if(res.data.code==200){
    ElMessage({
      type: 'success',
      message: '执行成功!'
    })
  }else{
    ElMessage({
      type: 'error',
      message: res.data.msg,
    })
    initUserList();
  }
}


const handleResetPassword=async (id)=>{
  const res=await requestUtil.get("sys/user/resetPassword/"+id)
  if(res.data.code==200){
    ElMessage({
      type: 'success',
      message: '重置成功!'
    })
    initUserList();
  }else{
    ElMessage({
      type: 'error',
      message: res.data.msg,
    })
  }
}


const handleSelectionChange=(selection)=>{
  console.log("勾选了");
  console.log(selection);
  multipleSelection.value=selection;
  delBtnStatus.value=selection.length==0;
}

const handleDelete=async (id)=>{
  var ids = [];
  if(id){
    ids.push(id);
  }else{
    multipleSelection.value.forEach(row=>{
      ids.push(row.id);
    })
  }
  const res=await requestUtil.post("sys/user/delete",ids)
  if(res.data.code==200){
    ElMessage({
      type: 'success',
      message: '执行成功!'
    })
    initUserList();
  }else{
    ElMessage({
      type: 'error',
      message: res.data.msg,
    })
  }
}


const handleDialogValue=(userId)=>{
  console.log(userId);
  if(userId){
    id.value=userId;
    dialogTitle.value="用户修改";
  }else{
    id.value=-1;
    dialogTitle.value="用户添加";
  }
    dialogVisible.value=true;
}



const tableData=ref([]);

const total=ref(0);

const queryForm=ref({
  query:'',
  pageNum:1,
  pageSize:5
})

const initUserList=async()=>{
  const res=await requestUtil.post("sys/user/list",queryForm.value);
  tableData.value=res.data.data.userList;
  total.value=res.data.data.total;
}

initUserList();

const handleSizeChange=(pageSize)=>{
  queryForm.value.pageNum=1;
  queryForm.value.pageSize=pageSize;
  initUserList();
}

const handleCurrentChange=(pageNum)=>{
  queryForm.value.pageNum=pageNum;
  initUserList();
}




</script>

<style lang="scss" scoped>

.header{
  padding-bottom: 16px;
  box-sizing: border-box;
}

.el-pagination{
  float: right;
  padding: 20px;
  box-sizing: border-box;
}

::v-deep th.el-table__cell{
  word-break: break-word;
  background-color: #f8f8f9 !important;
  color: #515a6e;
  height: 40px;
  font-size: 13px;

}

.el-tag--small {
  margin-left: 5px;
}
</style>

dialog.vue代码如下:
<template>

  <el-dialog
    v-model="dialogVisible"
    :title="dialogTitle"
    width="30%"
    @close="handleClose"
  >
       <el-form
        ref="formRef"
        :model="form"
        :rules="rules"
        label-width="100px"
    >
      <el-form-item label="用户名" prop="username">
        <el-input v-model="form.username" :disabled="form.id==-1?false:'disabled'"  />
        <el-alert
            v-if="form.id==-1"
            title="默认初始密码:123456"
            :closable="false"
            style="line-height: 10px;"
            type="success" >
        </el-alert>
      </el-form-item>

      <el-form-item label="手机号" prop="phonenumber">
        <el-input v-model="form.phonenumber" />
      </el-form-item>

      <el-form-item label="邮箱" prop="email">
        <el-input v-model="form.email" />
      </el-form-item>

      <el-form-item label="状态" prop="status">
        <el-radio-group v-model="form.status">
          <el-radio :label="'0'">正常</el-radio>
          <el-radio :label="'1'">禁用</el-radio>
        </el-radio-group>
      </el-form-item>


      <el-form-item label="备注" prop="remark">
        <el-input v-model="form.remark" type="textarea" :rows="4"/>
      </el-form-item>


    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" @click="handleConfirm">确认</el-button>
        <el-button @click="handleClose"
          >取消</el-button
        >
      </span>
    </template>
  </el-dialog>

</template>

<script setup>
import {defineEmits, defineProps,ref,watch } from "vue"
import requestUtil,{getServerUrl} from "@/util/request";
import { ElMessage } from 'element-plus'

const props=defineProps(
    {
      id:{
        type:Number,
        default:-1,
        required:true
      },
      dialogTitle:{
        type:String,
        default:'',
        required:true
      },
      dialogVisible:{
        type:Boolean,
        default:false,
        required:true
      }
    }
)

const dialogVisible=ref(false);


const form=ref({
  id:-1,
  username:"",
  password:"123456",
  status:"0",
  phonenumber:"",
  email:"",
  remark:""
})

const checkUsername = async (rule, value, callback) => {
  if(form.value.id==-1){
    const res=await requestUtil.post("sys/user/checkUserName",{username:form.value.username});
    if (res.data.code==500) {
      callback(new Error("用户名已存在!"));
    } else {
      callback();
    }
  }else{
    callback();
  }

}


const rules=ref({
  username:[
    { required: true, message: '请输入用户名'},
    { required: true, validator: checkUsername, trigger: "blur" }
  ],
  email: [{ required: true, message: "邮箱地址不能为空", trigger: "blur" }, { type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
  phonenumber: [{ required: true, message: "手机号码不能为空", trigger: "blur" }, { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }],
})

const formRef=ref(null)

const initFormData=async(id)=>{
  const res=await requestUtil.get("sys/user/"+id);
  console.log("根据id查询的值:");
  console.log(res);
  form.value=res.data.data.sysUser;
}

watch(
    ()=>props.dialogVisible,
    ()=>{
      let id=props.id;
      console.log("id="+id)
      if(id!=-1){
        initFormData(id);
      }else{
        form.value={
          id:-1,
          username:"",
          password:"123456",
          status:"0",
          phonenumber:"",
          email:"",
          remark:""
        }
      }
    }
)

const emits=defineEmits(['update:modelValue','initUserList'])

const handleClose=()=>{
  emits('update:modelValue',false)
}

const handleConfirm=()=>{
  formRef.value.validate(async(valid)=>{
    if(valid){
      let result=await requestUtil.post("sys/user/save",form.value);
      let data=result.data;
      if(data.code==200){
        ElMessage.success("执行成功!")
        formRef.value.resetFields();
        //调用父组件刷新数据
        emits("initUserList")
        handleClose();
      }else{
        ElMessage.error(data.msg);
      }
    }else{
      console.log("fail");
    }
  })
}

</script>

<style lang="scss" scoped>

</style>
roleDialog.vue代码如下:
<template>
  <el-dialog
    model-value="roleDialogVisible"
    title="分配角色"
    width="30%"
    @close="handleClose"
  >

    <el-form
        ref="formRef"
        :model="form"
        label-width="100px"
    >

      <el-checkbox-group v-model="form.checkedRoles">
        <el-checkbox v-for="role in form.roleList" :id="role.id" :key="role.id" :label="role.id"  name="checkedRoles" >{{role.name}}</el-checkbox>
      </el-checkbox-group>

    </el-form>

    <template #footer>
      <span class="dialog-footer">
        <el-button type="primary" @click="handleConfirm">确认</el-button>
        <el-button  @click="handleClose">取消</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>

import {defineEmits, defineProps, ref, watch} from "vue";
import requestUtil,{getServerUrl} from "@/util/request";
import { ElMessage } from 'element-plus'


  const props=defineProps(
      {
        id:{
          type:Number,
          default:-1,
          required:true
        },
        roleDialogVisible:{
          type:Boolean,
          default:false,
          required:true
        },
        sysRoleList:{
          type:Array,
          default:[],
          required:true
        }
      }
  )


const form=ref({
  id:-1,
  roleList:[],
  checkedRoles:[]
})


const formRef=ref(null)

const initFormData=async(id)=>{
  const res=await requestUtil.get("sys/role/listAll");
  form.value.roleList=res.data.data.roleList;
  form.value.id=id;
}


  watch(
      ()=>props.roleDialogVisible,
      ()=>{
        let id=props.id;
        console.log("id="+id);
        if(id!=-1){
          form.value.checkedRoles=[]
          props.sysRoleList.forEach(item=>{
            form.value.checkedRoles.push(item.id);
          })
          initFormData(id);
        }
      }
  )


  const emits=defineEmits(['update:modelValue','initUserList']);

  const handleClose=()=>{
    emits('update:modelValue',false);
  }

  const handleConfirm=()=>{
    formRef.value.validate(async(valid)=>{
      if(valid){
          let result=await requestUtil.post("sys/user/grantRole/"+form.value.id,form.value.checkedRoles);
          let data=result.data;
          if(data.code==200){
            ElMessage.success("执行成功!")

            emits("initUserList");
            handleClose();
          }else{
            ElMessage.error(data.msg);
          }
      }else{
        console.log("fail");
      }
    })
  }

</script>

<style scoped>

</style>

后端控制器代码
用户控制器代码如下:
package com.xuguoguo.contorller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuguoguo.common.MyConstant;
import com.xuguoguo.common.ResponseData;
import com.xuguoguo.common.Result;
import com.xuguoguo.entity.PageBean;
import com.xuguoguo.entity.SysRole;
import com.xuguoguo.entity.SysUser;
import com.xuguoguo.entity.SysUserRole;
import com.xuguoguo.service.SysRoleService;
import com.xuguoguo.service.SysUserRoleService;
import com.xuguoguo.service.SysUserService;
import com.xuguoguo.utils.DateUtil;
import com.xuguoguo.utils.StringUtil;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;

/**
 @Package: com.xuguoguo.contorller
 @ClassName: SysUsersController
 @Author: XuGuoGuo
 @CreateTime: 2023/12/18-8:43
 @Description:
 */
@RestController
@RequestMapping("/sys/user")
public class SysUsersController {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @Value("${avatarImagesFilePath}")
    private String avatarImagesFilePath;
    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    /**
     * 用户角色授权
     * @param userId
     * @param roleIds
     * @return
     */
    @Transactional
    @PostMapping("/grantRole/{userId}")
    @PreAuthorize("hasAuthority('system:user:role')")
    public ResponseData grantRole(@PathVariable("userId") Long userId,@RequestBody Long[] roleIds){
        List<SysUserRole> userRoleList=new ArrayList<>();
        Arrays.stream(roleIds).forEach(r -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setRoleId(r);
            sysUserRole.setUserId(userId);
            userRoleList.add(sysUserRole);
        });
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().eq("user_id",userId));
        sysUserRoleService.saveBatch(userRoleList);
        return new ResponseData("操作成功",200);
    }

    /**
     * 更新status状态
     * @param id
     * @param status
     * @return
     */
    @GetMapping("/updateStatus/{id}/status/{status}")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public ResponseData updateStatus(@PathVariable(value = "id")Integer id,
                                     @PathVariable(value = "status")String status){
        SysUser sysUser = sysUserService.getById(id);
        sysUser.setStatus(status);
        sysUserService.saveOrUpdate(sysUser);
        return new ResponseData("操作成功",200);
    }


    /**
     * 重置密码
     * @param id
     * @return
     */
    @GetMapping("/resetPassword/{id}")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public ResponseData resetPassword(@PathVariable(value = "id")Integer id){
        SysUser sysUser = sysUserService.getById(id);
        sysUser.setPassword(bCryptPasswordEncoder.encode(MyConstant.DEFAULT_PASSWORD));
        sysUser.setUpdateTime(new Date());
        sysUserService.updateById(sysUser);
        return new ResponseData("操作成功",200);
    }




    /**
     * 删除
     * @param ids
     * @return
     */
    @Transactional
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('system:user:delete')")
    public ResponseData delete(@RequestBody Long[] ids){
        //操作两个数据表【一个用户信息表、一个是用户角色信息关联表】
        sysUserService.removeByIds(Arrays.asList(ids));
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().in("user_id",ids));
        return new ResponseData("操作成功",200);
    }



    /**
     * 添加或者修改
     * @param sysUser
     * @return
     */
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('system:user:add')"+"||"+"hasAuthority('system:user:edit')")
    public ResponseData save(@RequestBody SysUser sysUser){
        if(sysUser.getId()==null || sysUser.getId()==-1){
            sysUser.setCreateTime(new Date());
            sysUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getPassword()));
            sysUser.setId(null);//自增
            sysUserService.save(sysUser);
        }else{
            sysUser.setUpdateTime(new Date());
            sysUserService.updateById(sysUser);
        }
        return new ResponseData("操作成功",200);
    }

    /**
     * 根据id查询
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('system:user:query')")
    public ResponseData findById(@PathVariable(value = "id")Integer id){
        SysUser sysUser = sysUserService.getById(id);
        Map<String,Object> map=new HashMap<>();
        map.put("sysUser",sysUser);
        return new ResponseData(map);
    }

    /**
     * 验证用户名
     * @param sysUser
     * @return
     */
    @PostMapping("/checkUserName")
    @PreAuthorize("hasAuthority('system:user:query')")
    public ResponseData checkUserName(@RequestBody SysUser sysUser){
        if(sysUserService.getByUsername(sysUser.getUsername())==null){
            return new ResponseData("可以使用!",200);
        }else{
            return new ResponseData("用户名已存在!",500);
        }
    }


    /**
     * 根据条件分页查询用户信息
     * @param pageBean
     * @return
     */
    @PostMapping("/list")
    @PreAuthorize("hasAuthority('system:user:query')")
    public ResponseData list(@RequestBody PageBean pageBean){
        String query=pageBean.getQuery().trim();
        Page<SysUser> pageResult = sysUserService.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize())
                ,new QueryWrapper<SysUser>().like(StringUtil.isNotEmpty(query),"username",query));
        List<SysUser> userList = pageResult.getRecords();
        //遍历集合
        for(SysUser user:userList){
            List<SysRole> roleList = sysRoleService.list(new QueryWrapper<SysRole>().
                    inSql("id", "select role_id from sys_user_role where user_id=" + user.getId()));
            user.setSysRoleList(roleList);
        }
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("userList",userList);
        resultMap.put("total",pageResult.getTotal());
        return new ResponseData("请求成功!",200,resultMap);
    }


    /**
     * 上传用户头像图片
     * @param file
     * @return
     * @throws Exception
     */
    @RequestMapping("/uploadImage")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public Map<String,Object> uploadImage(MultipartFile file)throws Exception{
        Map<String,Object> resultMap=new HashMap<>();
        if(!file.isEmpty()){
            // 获取文件名
            String originalFilename = file.getOriginalFilename();
            String suffixName=originalFilename.substring(originalFilename.lastIndexOf("."));
            //防止重复的文件名[使用时间或者uuid之类的唯一值处理即可]
            String newFileName= DateUtil.getCurrentDateStr()+suffixName;
            FileUtils.copyInputStreamToFile(file.getInputStream(),new File(avatarImagesFilePath+newFileName));
            resultMap.put("code",0);
            resultMap.put("msg","上传成功");
            Map<String,Object> dataMap=new HashMap<>();
            dataMap.put("title",newFileName);
            dataMap.put("src","image/userAvatar/"+newFileName);
            resultMap.put("data",dataMap);
        }
        return resultMap;
    }



    /**
     * 修改用户头像
     * @param sysUser
     * @return
     */
    @RequestMapping("/updateAvatar")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public ResponseData updateAvatar(@RequestBody SysUser sysUser){
        SysUser currentUser = sysUserService.getById(sysUser.getId());
        currentUser.setUpdateTime(new Date());
        currentUser.setAvatar(sysUser.getAvatar());
        sysUserService.updateById(currentUser);
        return new ResponseData("操作成功",200);
    }

    /**
     * 修改密码
     * @param sysUser
     * @return
     */
    @PostMapping("/updateUserPwd")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public ResponseData updateUserPwd(@RequestBody SysUser sysUser){
        SysUser currentUser = sysUserService.getById(sysUser.getId());
        if(bCryptPasswordEncoder.matches(sysUser.getOldPassword(),currentUser.getPassword())){
            currentUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getNewPassword()));
            currentUser.setUpdateTime(new Date());
            sysUserService.updateById(currentUser);
            return new ResponseData("操作成功",200);
        }else{
            return new ResponseData("输入原密码错误!",500);
        }
    }


//    /**
//     * 添加或者修改
//     * @param sysUser
//     * @return
//     */
//    @PostMapping("/save")
//    @PreAuthorize("hasAuthority('system:user:add')"+"||"+"hasAuthority('system:user:edit')")
//    public ResponseData save(@RequestBody SysUser sysUser){
//        if(sysUser.getId()==null || sysUser.getId()==-1){
//
//        }else{
//            //此处修改更新时间可以使用MybatisPlus中的自动填充策略去实现【解决硬编码问题】
//            sysUser.setUpdateTime(new Date());
//            sysUserService.updateById(sysUser);
//        }
//        return new ResponseData("操作成功",200);
//    }




}
角色控制器代码如下:
package com.xuguoguo.contorller;

import com.xuguoguo.common.ResponseData;
import com.xuguoguo.entity.SysRole;
import com.xuguoguo.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 @Package: com.xuguoguo.contorller
 @ClassName: SysRoleController
 @Author: XuGuoGuo
 @CreateTime: 2023/12/18-22:52
 @Description:
 */



@RestController
@RequestMapping("/sys/role")
public class SysRoleController {

    @Autowired
    private SysRoleService sysRoleService;

    @GetMapping("/listAll")
    @PreAuthorize("hasAuthority('system:role:query')")
    public ResponseData listAll(){
        Map<String,Object> resultMap=new HashMap<>();
        List<SysRole> roleList = sysRoleService.list();
        resultMap.put("roleList",roleList);
        return new ResponseData(resultMap);
    }
}

小结

提示:本小结主要助理的是用户模块相关的操作,基本上就是crud【增删改查】的操作,穿插了用户分配角色信息的处理等!!!

本章的第九小节完毕,敬请期待后续更新(可留言需要学习哪方面的内容哈)!如果需要源码或者工具的朋友们可关注微信公众号"锅锅编程生活"或者扫描二维码关注回复关键字/后台留言获取即可!

在这里插入图片描述

文章来源:https://blog.csdn.net/xu772710255/article/details/135287609
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。