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

今天开始使用 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-plus组件库提供的相关标签实现快速搭建样式,我们采用卡片样式,最外层用el-card进行包裹:

<template>
  <el-card class="box-card">
  </el-card>
</template>

卡片里面的样式就可以根据自己的喜好随意搭配了,这里我存放了一个按钮、表格和分页器:

<el-card class="box-card">
  <!-- 卡片顶部添加按钮 -->
  <el-button type="primary" size="default" icon="Plus">添加品牌</el-button>
  <!-- 表格组件,用于展示已有的平台数据 -->
  <el-table style="margin: 10px 0px" border>
    <el-table-column
      label="序号"
      width="80px"
      align="center"
    ></el-table-column>
    <el-table-column label="品牌名称"></el-table-column>
    <el-table-column label="品牌Logo"></el-table-column>
    <el-table-column label="品牌操作"></el-table-column>
  </el-table>
  <!-- 分页器组件 -->
  <el-pagination
    v-model:current-page="pageNo"
    v-model:page-size="limit"
    :page-sizes="[3, 5, 7, 9]"
    background="true"
    layout="prev, pager, next, jumper, ->, sizes, total"
    :total="400"
  />
</el-card>

通过JS定义相关变量实现响应式数据:

<script setup lang="ts">
import { ref } from 'vue'
// 当前的页码
let pageNo = ref<number>(1)
// 每页展示多少条数据
let limit = ref<number>(3)
</script>

最后实现的静态页面效果如下所示:

品牌管理数据展示

在显示内容方面,我们可用借助Table组件库中的prop属性进行展示内容

对应的数据就会展示出来:

使用prop默认是以div包裹进行展示的,当然这里也可以使用template插槽进行展示数据,接下来的图片和操作都可以使用插槽来完成:

分页器点击相关操作

接下来开始对点击分页器进行相关数据切换操作,这里我们采用的是组件库中的分页器给我们提供的相关API进行操作:

我们在点击分页按钮后,其API会自动将相关的页数进行一个注入,所以我们不需要进行传递参数来实现:

因为是自动注入相关的页码值数据,所以我们也可以直接调用获取数据的方法,不需要再额外定义一个新的函数,定义分页数也可以采用相同的方法,不过为了让在点击分页数之后,页码值会跳转到第一页,可以传递一个默认参数,如果没有传递参数的话,默认就是1,传递的话就会覆盖默认值:

对话框静态搭建

在项目中添加品牌和修改品牌的相关数据都需要借助对话框来实现,所以这里就需要简单的搭建一下对话框并使用,如下借助组件库使用:

<!-- 对话框组件:在添加品牌和修改已有品牌的业务时侯使用该结构 -->
<el-dialog v-model="dialogFormVisible" title="添加品牌">
  <el-form style="width: 80%">
    <el-form-item label="品牌名称" label-width="80px">
      <el-input placeholder="请您输入品牌名称"></el-input>
    </el-form-item>
    <el-form-item label="品牌LOGO" label-width="80px">
      <el-upload
        class="avatar-uploader"
        action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
        :show-file-list="false"
        :on-success="handleAvatarSuccess"
        :before-upload="beforeAvatarUpload"
      >
        <img v-if="imageUrl" :src="imageUrl" class="avatar" />
        <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
      </el-upload>
    </el-form-item>
  </el-form>
  <!-- 具名插槽:设置相关按钮 -->
  <template #footer>
    <el-button type="primary" size="default" @click="cancel">
      取消
    </el-button>
    <el-button type="primary" size="default" @click="confirm">
      确定
    </el-button>
  </template>
</el-dialog>

当然我们要为添加品牌和修改品牌的按钮设置点击事件来更改

// 添加品牌按钮的回调
const addTrademark = () => {
  // 对话框显示
  dialogFormVisible.value = true
}
// 修改已有品牌数据的回调
const updateTrademark = () => {
  // 对话框显示
  dialogFormVisible.value = true
}
// 对话框底部取消按钮
const cancel = () => {
  // 对话框隐藏
  dialogFormVisible.value = false
}
// 对话框底部确定按钮
const confirm = () => {
  // 对话框隐藏
  dialogFormVisible.value = false
}

最后呈现的结果如下:

接下来给上传图片设置相关的格式校验:

// 上传图片组件,钩子是在图片上传成功之前触发,上传文件之前可以约束文件类型与大小
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  if (
    rawFile.type == 'image/png' ||
    rawFile.type == 'image/jpg' ||
    rawFile.type == 'image/gif' ||
    rawFile.type == 'image/jpeg'
  ) {
    if (rawFile.size / 1024 / 1024 < 4) {
      return true
    } else {
      ElMessage({
        type: 'error',
        message: '上传文件大小应小于4M',
      })
    }
  } else {
    ElMessage({
      type: 'error',
      message: '上传文件格式务必PNG|JPG|GIF|JPEG',
    })
    return false
  }
}
// 图片上传成功的钩子
const handleAvatarSuccess: UploadProps['onSuccess'] = (response) => {
  // 收集图片的地址
  trademarkParams.logoUrl = response.data
}

实现添加修改删除业务的功能

接下来实现数据的增删改操作,当然这里的话也是要和后端搭配借助相关的接口实现,如下:

// 书写品牌管理模块的接口
import request from '@/utils/request'
// 引入ts类型
import type { TradeMarkResponseData, TradeMark } from './type'
// 品牌管理模块接口地址
enum API {
  // 获取已有品牌接口
  TRADEMAKE_URL = '/admin/product/baseTrademark/',
  // 添加品牌
  ADDTRADEMAKE_URL = '/admin/product/baseTrademark/save',
  // 修改品牌
  UPDATETRADEMAKE_URL = '/admin/product/baseTrademark/update',
  // 删除已有品牌数据
  DELETE_URL = '/admin/product/baseTrademark/remove/',
}
// 获取已有品牌的接口方法:page:获取第几页;limit:获取几个已有品牌的数据
export const reqHasTrademark = (page: number, limit: number) =>
  request.get<any, TradeMarkResponseData>(API.TRADEMAKE_URL + `${page}/${limit}`)
// 添加和修改已有品牌接口方法
export const reqAddOrUpdateTrademark = (data: TradeMark) => {
  // 修改已有品牌的数据
  if (data.id) {
    return request.put<any, any>(API.UPDATETRADEMAKE_URL, data)
  } else {
    // 新增品牌数据
    return request.post<any, any>(API.ADDTRADEMAKE_URL, data)
  }
}
// 删除某一个已有品牌的数据
export const reqDeleteTrademark = (id: number) => request.delete<any, any>(API.DELETE_URL + id)

在点击对话框的确定按钮后调用添加数据业务,因为添加数据是不需要id的,后端会自动帮助我们生成相应的id,但是修改业务需要借助相应id,所以这里我们通过id的与否来判断是我们是选择添加品牌还是修改品牌:

// 对话框底部确定按钮
const confirm = async () => {
  let result: any = await reqAddOrUpdateTrademark(trademarkParams)
  // 添加品牌成功
  if (result.code == 200) {
    // 对话框隐藏
    dialogFormVisible.value = false
    // 弹出提示信息
    ElMessage({
      type: 'success',
      message: trademarkParams.id ? '修改品牌成功' : '添加品牌成功',
    })
    // 再次发请求获取已有全部的品牌数据
    hasTrademark(trademarkParams.id ? pageNo.value : 1)
  } else {
    // 添加品牌失败
    ElMessage({
      type: 'error',
      message: trademarkParams.id ? '修改品牌失败' : '添加品牌失败',
    })
  }
}

当我们点击修改按钮后,通过点击事件会自动获取当前修改品牌的相关数据,因为修改数据是具有其ID的,所以这里我们通过ES6语法对trademarkParams进行一个合并:

// 修改已有品牌数据的回调
const updateTrademark = (row: TradeMark) => {
  // 对话框显示
  dialogFormVisible.value = true
  // // 展示已有品牌的数据
  // trademarkParams.id = row.id
  // trademarkParams.tmName = row.tmName
  // trademarkParams.logoUrl = row.logoUrl
  // 使用ES6合并语法
  Object.assign(trademarkParams, row)
}

删除数据的方式同样简单,这里借助组件库中的气泡提示框进行书写,通过相关事件confirm来对其数据进行一个删除:

// 删除按钮的回调
const removeTradeMark = async (id: number) => {
  // 点击确定按钮删除已有品牌请求
  let result = await reqDeleteTrademark(id)
  if (result.code == 200) {
    ElMessage({
      type: 'success',
      message: '删除品牌成功',
    })
    // 再次发请求获取已有全部的品牌数据
    hasTrademark(trademarkArr.value.length > 1 ? pageNo.value : pageNo.value - 1)
  } else {
    ElMessage({
      type: 'error',
      message: '删除品牌失败',
    })
  }
}

呈现的结果如下:

表单自定义规则校验

接下来仍然需要对对话框中的文字和图片区域进行相关校验,校验规则如下:

// 品牌自定义校验规则(文字)
const validatorTmName = (_rule: any, value: any, callback: any) => {
  if (value.trim().length >= 2) {
    callback()
  } else {
    // 校验未通过返回的错误信息
    callback(new Error('品牌名称位数必须大于等于俩位'))
  }
}
// 品牌自定义校验规则(图片)
const validatorLogoUrl = (_rule: any, value: any, callback: any) => {
  // 如果图片上传
  if (value) {
    callback()
  } else {
    callback(new Error('LOGO图片务必上传!'))
  }
}
// 设置表单校验规则对象
const rules = {
  tmName: [{ required: true, trigger: 'blur', validator: validatorTmName }],
  logoUrl: [{ required: true, trigger: 'change', validator: validatorLogoUrl }],
}

设置完校验规则之后,我们需要在点击按钮之后对整个表单进行校验,如果校验不通过需要提示,当然这里需要通过ref来获取form表单的数据进行验证:

验证完成之后,在点击确定或者重新打开表单时需要清除相关的表单验证规则,因为初始进行是没有进行表单验证的,所以我们要使用可选链操作符进行判断:

最终达到的效果如下:

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

猜你喜欢

转载自blog.csdn.net/qq_53123067/article/details/131125776