Vue--》Vue3打造可扩展的项目管理系统后台的完整指南(九)

news2024/11/25 5:38:57

今天开始使用 vue3 + ts 搭建一个项目管理的后台,因为文章会将项目的每一个地方代码的书写都会讲解到,所以本项目会分成好几篇文章进行讲解,我会在最后一篇文章中会将项目代码开源到我的GithHub上,大家可以自行去进行下载运行,希望本文章对有帮助的朋友们能多多关注本专栏,学习更多前端vue知识,然后开篇先简单介绍一下本项目用到的技术栈都有哪几个方面(阅读本文章能够学习到的技术):

vite:快速轻量且功能丰富的前端构建工具,帮助开发人员更高效构建现代Web应用程序。

pnpm:高性能、轻量级npm替代品,帮助开发人员更加高效地处理应用程序的依赖关系。

Vue3:Vue.js最新版本的用于构建用户界面的渐进式JavaScript框架。

TypeScript:JavaScript的超集,提供了静态类型检查,使得代码更加健壮。

Animate:基于JavaScript的动画框架,它使开发者可以轻松创建各种炫酷的动画效果。

vue-router:Vue.js官方提供的路由管理器与Vue.js紧密耦合,非常方便与Vue.js一同使用。

Pinia:Vue3构建的Vuex替代品,具有响应式能力,提供非常简单的 API,进行状态管理。

element-plus:基于Vue.js 3.0的UI组件库,用于构建高品质的响应式Web应用程序。

axios:基于Promise的HTTP客户端,可以在浏览器和node.js中使用。

three:基于JavaScript的WebGL库,开发者可以编写高性能、高质量的3D场景呈现效果。

echarts:基于JavaScript的可视化图表库,支持多种类型的图表,可根据需要自行安装。

当然还有许多其他的需要安装的第三方库,这里就不再一一介绍了,在项目中用到的地方自行会进行讲解,大家自行学习即可,现在就让我们走进vue3+ts的实战项目吧。

目录

用户管理模块搭建

实现添加与修改业务

实现分配角色任务

实现删除业务

实现搜索重置业务


用户管理模块搭建

用户管理模块的搭建和之前几个模块搭建类似,也是采用element组件库提供的相关组件进行处理,在卡片中防止输入框、按钮、以及表格和分页器等组件,具体部分代码如下:

搭建完相关静态之后,通过编写接口函数以及相关ts类型获取相关数据,如下:

// 用户管理模块的接口
import request from '@/utils/request'
// 引入ts类型
import type { UserResponseData } from './type'
// 枚举地址
enum API {
  // 获取全部已有用户账号信息
  ALLUSER_URL = '/admin/acl/user/',
}
// 获取用户账号信息的接口
export const reqUserInfo = (page: number, limit: number) =>
  request.get<any, UserResponseData>(API.ALLUSER_URL + `${page}/${limit}`)

编写完接口函数之后,就可以传递相关参数获取数据,然后将数据放置在表格中进行展示,如下:

<script setup lang="ts">
import { ref, onMounted } from 'vue'
// 引入接口函数
import { reqUserInfo } from '@/api/acl/user'
// 引入ts类型
import type { UserResponseData, Records } from '@/api/acl/user/type'
// 当前的页码值
let pageNo = ref<number>(1)
// 页码展示的数据
let pageSize = ref<number>(5)
// 用户的总个数
let total = ref<number>(0)
// 存储全部用户的数组
let userArr = ref<Records>([])

// 组件挂载完毕执行函数
onMounted(() => {
  getHasUser()
})
// 获取全部已有的信息
const getHasUser = async (pager = 1) => {
  pageNo.value = pager
  let result: UserResponseData = await reqUserInfo(pageNo.value, pageSize.value)
  if (result.code == 200) {
    total.value = result.data.total
    userArr.value = result.data.records
  }
}
// 更新当前页码能够显示的条数
const handler = () => {
  getHasUser()
}
</script>

将定义的响应式变量数据赋予相关数据值之后,就可以在表格中进行相关的展示了,因为前几篇文章已经讲解过几次关于分页器进行页面切换效果的原理,这里就不再赘述,如下:

最终实现的效果为:

实现添加与修改业务

实现添加和修改业务需要对数据进行修改,这里仍然需要借助接口来实现,如下进行接口编写:

编写完接口后就可以对数据进行处理了,这里我采用element组件库中的抽屉功能实现添加和修改数据,如下:

<!-- 抽屉结构:完成添加或修改新的用户账号信息 -->
<el-drawer v-model="drawer">
  <template #header>
    <h4>添加用户</h4>
  </template>
  <template #default>
    <el-form>
      <el-form-item label="用户姓名">
        <el-input placeholder="请输入用户姓名" v-model="userParams.username"></el-input>
      </el-form-item>
      <el-form-item label="用户昵称">
        <el-input placeholder="请输入用户昵称" v-model="userParams.name"></el-input>
      </el-form-item>
      <el-form-item label="用户密码">
        <el-input placeholder="请输入用户密码" v-model="userParams.password"></el-input>
      </el-form-item>
    </el-form>
  </template>
  <template #footer>
    <div style="flex: auto">
      <el-button @click="cancel">取消</el-button>
      <el-button type="primary" @click="save">确定</el-button>
    </div>
  </template>
</el-drawer>

给添加和修改数据的按钮绑定点击事件,对响应式数据drawer进行布尔值数据的切换用来控制抽屉的显示与隐藏,如下:

// 控制抽屉的显示与隐藏
let drawer = ref<boolean>(false)

当然为了对数据进行校验,我们可以设置自定义规则,给我们的数据进行相关的限制,如下:

接下来开始编写校验规则,如下:

// 校验用户名字的回调函数
const validatorUsername = (rule: any, value: any, callback: any) => {
  // 用户名字|昵称,长度至少五位
  if (value.trim().length >= 5) {
    callback()
  } else {
    callback(new Error('用户的名称至少五位!'))
  }
}
// 校验用户名称的回调函数
const validatorName = (rule: any, value: any, callback: any) => {
  // 用户名字|昵称,长度至少五位
  if (value.trim().length >= 5) {
    callback()
  } else {
    callback(new Error('用户的昵称至少五位!'))
  }
}
// 校验密码的回调函数
const validatorPassword = (rule: any, value: any, callback: any) => {
  // 用户名字|昵称,长度至少五位
  if (value.trim().length >= 6) {
    callback()
  } else {
    callback(new Error('用户的密码至少六位!'))
  }
}

// 表单校验的规则对象
const rules = {
  // 用户名字
  username: [{ required: true, trigger: 'blur', validator: validatorUsername }],
  // 用户昵称
  name: [{ required: true, trigger: 'blur', validator: validatorName }],
  // 密码
  password: [{ required: true, trigger: 'blur', validator: validatorPassword }],
}

编写完校验规则之后,在保存按钮处先进行表单校验,校验完成后才能执行保存回调后面的函数:

// 保存按钮的回调
const save = async () => {
  // 点击保存按钮的时候,务必需要保证表单全部符合条件再去发起请求
  await formRef.value.validate()
  // 保存按钮:添加|修改已有的用户账号信息
  let result = await reqAddOrUpdateUser(userParams)
  // 添加或更新成功
  if (result.code == 200) {
    drawer.value = false // 抽屉关闭
    // 提示消息
    ElMessage({ type: 'success', message: userParams.id ? '更新成功' : '添加成功' })
    // 获取最新的全部账号信息
    getHasUser()
  } else {
    drawer.value = false // 抽屉关闭
    // 提示消息
    ElMessage({ type: 'error', message: userParams.id ? '更新失败' : '添加失败' })
  }
}

注意:在校验规则书写完成之后,还要才重新点击添加处进行表单错误提示信息的一个清除

最终结果如下:

更新的业务很简单,只需要在点击更新按钮的回调处,将当前数据与初始数据进行一个合并即可:

// 更新已有用户按钮的回调
const updateUser = (row: User) => {
  // 抽屉显示出来
  drawer.value = true
  // 存储收集已有的账号信息
  Object.assign(userParams, row)
  // 清除上一次的错误的提示信息
  nextTick(() => {
    formRef.value.clearValidate('username')
    formRef.value.clearValidate('name')
  })
}

判断当前是处于添加页面还是修改页面,只需要对当前的数据是否存在id值校验即可:

最终结果如下:

实现分配角色任务

实现分配角色的任务,这里也借助了一个抽屉进行数据的显示,给分配角色按钮设置点击事件,并传入当前数据 row 作为参数,通过点击按钮触发点击事件来实现抽屉的显示与隐藏以及数据的合并:

// 分配角色按钮的回调
const setRole = (row: User) => {
  // 抽屉显示出来
  drawer1.value = true
  // 数据合并
  Object.assign(userParams, row)
}

给抽屉设置如下的样式进行选择,这里我设置了一些假数据进行展示:

<!-- 抽屉结构:用户某一个已有的账号进行职位分配 -->
<el-drawer v-model="drawer1">
  <template #header>
    <h4>分配角色</h4>
  </template>
  <template #default>
    <el-form>
      <el-form-item label="用户姓名">
        <el-input v-model="userParams.username" :disabled="true"></el-input>
      </el-form-item>
      <el-form-item label="职位列表">
        <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">
          全选
        </el-checkbox>
        <!-- 显示职位的复选框 -->
        <el-checkbox-group v-model="userRole" @change="handleCheckedCitiesChange">
          <el-checkbox v-for="(role, index) in allRole" :key="index" :label="role">{{ role }}</el-checkbox>
        </el-checkbox-group>
      </el-form-item>
    </el-form>
  </template>
  <template #footer>
    <div style="flex: auto">
      <el-button @click="cancel">取消</el-button>
      <el-button type="primary" @click="save">确定</el-button>
    </div>
  </template>
</el-drawer>

通过点击复选框来实现全选效果以及全选样式效果,如下:

// 全选复选框的change事件
const handleCheckAllChange = (val: boolean) => {
  userRole.value = val ? allRole.value : []
  isIndeterminate.value = false
}
// 底部复选框事件
const handleCheckedCitiesChange = (value: string[]) => {
  // 已经勾选的这些项目的长度
  const checkedCount = value.length
  checkAll.value = checkedCount === allRole.value.length
  // 顶部的复选框不确定的样式
  isIndeterminate.value = !(checkedCount === allRole.value.length)
}

最终实现的效果如下:

接下来通过编写接口,获取全部职位,当前账号拥有的职位接口以及给已有的用户分配相应角色的接口,如下:

编写完接口后,给分配角色按钮的点击事件设置接口函数,获取当前id数据的所有职位信息:

// 分配角色按钮的回调
const setRole = async (row: User) => {
  // 数据合并
  Object.assign(userParams, row)
  // 获取全部的职位的数据与当前用户已有的职位的数据
  let result: AllRoleResponseData = await reqAllrole(userParams.id as number)
  if (result.code == 200) {
    // 存储全部职位
    allRole.value = result.data.allRolesList
    // 存储当前用户已有的职位
    userRole.value = result.data.assignRoles
    // 抽屉显示出来
    drawer1.value = true
  }
}

获取完职位信息之后,编写相关的参数数据,给抽屉的确定按钮设置接口函数来对当前分配角色数据进行更新,如下:

// 确定按钮回调(分配职位)
const confirmClick = async () => {
  // 收集参数
  let data: SetRoleData = {
    userId: userParams.id as number,
    roleIdList: userRole.value.map((item) => {
      return item.id as number
    }),
  }
  // 分配用户职位
  let result: any = await reqSetUserRole(data)
  if (result.code == 200) {
    // 提示信息
    ElMessage({ type: 'success', message: '分配职位成功!' })
    // 关闭抽屉
    drawer1.value = false
    // 获取更新后的数据,更新完毕留在当前页
    getHasUser(pageNo.value)
  }
}

最终实现的结果如下:

实现删除业务

删除业务有两种情况:一种是单个删除,另一种是批量删除,这里的话都需要对其撰写相应的接口

编写完接口后,首先我们先实习单个删除的功能,给单个删除按钮设置气泡显示框,然后通过confirm事件传递相应的id值,之后调用接口删除即可:

// 删除某一个用户
const deleteUser = async (userId: number) => {
  let result: any = await reqRemoveUser(userId)
  if (result.code == 200) {
    ElMessage({ type: 'success', message: '删除成功!' })
    getHasUser(userArr.value.length > 1 ? pageNo.value : pageNo.value - 1)
  } else {
    ElMessage({ type: 'error', message: '删除失败!' })
  }
}

批量删除业务,这里需要借助表格的一个监听事件,监听当前选择的是哪个数据的id,如下:

通过监听函数,将获取到的值在存储在响应式变量当中去:

// table复选框勾选的时候会触发的事件
const selectChange = (value: any) => {
  selectIdArr.value = value
}

存储完变量之后,通过map函数将数组中的id数据提取出来,作为参数传递到批量删除接口函数中

// 批量删除
const deleteSelectUser = async () => {
  // 整理批量删除的参数
  let idsList: any = selectIdArr.value.map((item) => {
    return item.id
  })
  // 批量删除的请求
  let result: any = await reqSelectUser(idsList)
  if (result.code == 200) {
    ElMessage({ type: 'success', message: '删除成功!' })
    getHasUser(userArr.value.length > 1 ? pageNo.value : pageNo.value - 1)
  }
}

实现搜索重置业务

实现重置业务可以定义一个响应式ref变量,然后通过v-model双向数据绑定,绑定到搜索输入框当中,接下来通过修改一下之前编写获取用户账号信息的接口,给其添加一个username属性,从而进行username名字的检索操作,如下:

然后接下来改变之前获取用户账号信息的参数,给其添加一个keyword,因为一开始你并没有进行搜索,所以一开始的keyword的属性值为空,所以获取的是全部数据,如下:

这里设置一个禁用的条件,只有你搜索输入框中有数据才能进行搜索,否则就是禁用状态,这也就保证了搜索按钮的点击事件触发的正确性,如下在保证输入框有数据,也就是keyword不为空的情况下进行搜索,调用获取信息数据的函数,也就会将我们关键字username信息进行找到:

// 搜索按钮的回调
const search = () => {
  // 根据关键字获取相应的数据
  getHasUser()
  // 清空关键字
  keyword.value = ''
}

重置按钮操作更为简单,给其绑定点击事件,然后调用我之前文件讲解header中刷新按钮的操作,对仓库中的数据进行一个更新并重新挂载,这也就保证了数据的重新获取,点击函数如下:

// 重置按钮
const reset = () => {
  settingStore.refsh = !settingStore.refsh
}
</script>

最终结果如下:

本项目的用户管理页面功能的搭建就讲解到这,下一篇文章将继续讲解其它模块的主体内容,关注博主学习更多前端vue知识,您的支持就是博主创作的最大动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/721100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Eclipse配置JVM启动参数

【参考】Eclipse设置jvm参数的三种方式

git、gitlab、github在windows下通用的操作笔记

前言&#xff1a;命令是在Git Bash 下输入的命令&#xff0c;GUI部分涉及到小乌龟git&#xff0c;可以自行安装&#xff0c;不同版本有差异&#xff0c;用git的新手也可以尝试 SourceTree 提供漂亮的图形化界面操作&#xff08;但是卡顿坑多&#xff0c;需三思&#xff09; 1、…

7月11入伏,进入三伏天dog days

三伏天&#xff0c;是一年中最热的日子,今年的三伏天始于7月11日。sanfu, the hottest time of the year begins on July 11th this year. 三伏&#xff0c;也称为中国的dog days,预示着一年中最热的三个阶段&#xff0c;每一阶段大约有10-20天。Sanfu, also called Chinas &qu…

基于FreeRTOS的嵌入式设备管理关键技术研究及实现(学习五重要)

操作系统任务框架 系统任务 空闲任务几乎存在于所有的嵌入式实时操作系统&#xff0c;用户无法自行关闭空闲任务。 空闲任务的作用主要是减少核心芯片的使用率&#xff0c;避免核心芯片的负载压力过大&#xff0c;保证系统的低功耗运行。 时钟节拍任务控制系统的延时函数和等待…

matlab画拟合直方图的脚本

都是一些简单的作图参数&#xff0c;可以自己按照matlab官方的指导去改style https://ww2.mathworks.cn/help/stats/histfit.html %-----------------------------------------------------------------------------------------------------------% %-----Function: Plot a h…

Proteus8.15 安装包下载及详细安装

Proteus8.15 安装包下载及详细安装 1.安装包链接&#xff0c;需要可自取&#xff0c;也可自行去官方下载最新版本 链接: https://pan.baidu.com/s/1Zcdr1hFo2RHCw88CXtY2bQ?pwdbuz6 提取码: buz6 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 –来自百度网盘超…

Redis 高可用和优化(主从复制、哨兵、集群)

目录 一&#xff1a;Redis 高可用 二&#xff1a; Redis 持久化 1、持久化的功能 2、Redis 提供两种方式进行持久化 3、 RDB 持久化 &#xff08;1&#xff09;触发条件 &#xff08;1.1&#xff09;手动触发 &#xff08;1.2&#xff09;自动触发 &#xff08;1.3&am…

[SSM]MyBatis常用技巧和参数处理

目录 八、MyBatis小技巧 8.1#{}和${} 8.2别名机制&#xff1a;typeAliases 8.3mappers ​编辑 8.4IDEA配置文件模板 8.5插入数据时获取自动生成的主键 九、MyBatis参数处理 9.1单个简单参数类型 9.2Map参数 9.3实体类参数 9.4多参数 9.5Param注解&#xff08;命名…

面向对象五大基本原则

面向对象五大基本原则 更多精彩 先案例后讲解&#xff0c;这里是代码教父&#xff0c;今天讲解面向对象的五大基本原则&#xff1a; 单一职责原则&#xff08;The Single Responsibility Principle&#xff09;开闭原则&#xff08;The Open-Closed Principle&#xff09;里氏…

javassit 01

Javassist&#xff1a; Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba &#xff08;千叶 滋&#xff09;所创建的。它已加入了开放源代码JBoss 应用服务器项目&#xff0c;通过使用Javassist对字节码操作为JB…

Java SSM 重制版(三)SpringSecurity

SpringSecurity 基于Spring6的重制版&#xff0c;截止目前&#xff0c;最新的版本是6.1.1版本。 前置课程&#xff1a;《Spring核心内容》《SpringMvc》《JavaWeb》《Java9-17新特性》 安全是开发者永远绕不开的话题&#xff0c;一个不安全的网站&#xff0c;往往存在着各种…

主机与虚拟机ubuntu网络无法ping通问题

一. 主机与虚拟机无法ping通问题 在嵌入式开发中&#xff0c;经过会涉及网络方面的问题。最常用到的是开发板在 虚拟机&#xff08;ubuntu&#xff09;通过NFS服务挂载到ubuntu中&#xff0c;这里就涉及网络是否可以ping通问题。 开发板 ping 通 ubuntu虚拟机系统的前提&…

基于matlab使用视频和深度学习进行手势识别(附源码)

一、前言 此示例首先演示如何使用预训练的SlowFast视频分类器执行手势识别&#xff0c;然后演示如何使用迁移学习在自定义手势识别数据集上训练分类器。 基于视觉的人类手势识别涉及使用一组视频帧预测手势&#xff0c;例如挥手打招呼、手语手势或鼓掌。手势识别的一个吸引人…

启动失败之源发行版 17 需要目标发行版 17

一、java: 警告: 源发行版 17 需要目标发行版 17 1.1.原因 :JDK 版本不对。 这里可以看到&#xff0c;项目需要的是JDK17&#xff0c;而我这里用的是JDK1.8。 1.2.修改 这里有两种操作&#xff0c;一种是修改项目版本&#xff0c;一种是修改JDK版本。无论是哪一种&#xff0…

CentOS7使用ping命令测试主机或者外部网络不通(已解决)

CentOS7使用ping命令测试主机或外部网路显示“目标主机不可达”或者其他原因失败。 说明 当尝试了所有修改配置&#xff0c;关闭防火墙等操作之后&#xff0c;还是没有成功的条件下。 查看计算机中的VMware相关的服务是否打开。 此电脑–右击–管理–服务与应用程序–服务 …

【小吉带你学Git】Git命令(用户签名,本地库,暂存区,文件,版本 等命令)

&#x1f38a;专栏【Git】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f33a;欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f354;设置用户签名⭐命令⭐如何在Windows上面查看自己的签名 &am…

eNSP-静态路由表的配置

eNSP-静态路由表的配置 文章目录 eNSP-静态路由表的配置一、拓扑结构二、关键语句三、完整代码四、测试验证 一、拓扑结构 二、关键语句 ip route-static x.x.x.x y z.z.z.z 语法&#xff1a;目标网段 掩码 下一跳 例如 PC1所在网段访问PC2所在网段 在AR1中输入 ip route-st…

scratch 鼠标控制角色移动

scratch 鼠标控制角色 本程序使用鼠标操作“机器人”角色跟随鼠标&#xff0c;距离较小时暂停移动&#xff1b;“小狗”角色连续在随机位置生成、水平移动、碰到边缘反弹、碰到“机器人”角色时删除。 目前scratch程序的制作已经告一段落了&#xff0c;进一步开发需要更多规划…

Redis【实战篇】---- 达人探店

Redis【实战篇】---- 达人探店 1. 达人探店 - 发布探店笔记2. 达人探店 - 查看探店笔记3. 达人探店 - 点赞功能4. 达人探店 - 点赞排行榜 1. 达人探店 - 发布探店笔记 发布探店笔记 探店笔记类似点评网站的评价&#xff0c;往往是图文结合。对应的表有两个&#xff1a; tb_bl…

集成算法概述

集成算法的基本思想&#xff1a;训练时用多种分类器一起完成同一份任务。 测试时对待测试样本分别通过不同的分类器&#xff0c;汇总最后的结果。投票方式&#xff0c;可分为软投票和硬投票。 集成算法一般有三种&#xff0c;分别是Bagging模型、Boosting模型和Stacking模型。 …