Vue3+Ts后台管理系统

品牌管理页面搭建

<template>
    <el-card class="box-card">
<!--      卡片顶部的添加按钮-->
      <el-button size="default" type="primary" icon="Plus" @click="addTrademark">添加品牌</el-button>
<!--      表格组件:用户展示已有的品牌的数据-->
      <el-table style="margin: 10px 0" border :data="trademarkArr">
        <el-table-column label="序号" type="index" width="80px" align="center"></el-table-column>
        <el-table-column label="品牌名称" align="center">
          <template #="{row}">
            <pre>{{row.tmName}}</pre>
          </template>
        </el-table-column>
        <el-table-column label="品牌Logo" align="center">
          <template #="{row}">
            <img :src="row.logoUrl" alt="小米要啥Logo" style="width: 100px;height: 100px">
          </template>
        </el-table-column>
        <el-table-column label="品牌操作" align="center">
          <template #="{row}">
            <el-button type="primary" size="default" icon="Edit" @click="updateTrademark(row)"></el-button>
            <el-popconfirm :title="`您确定删除${row.tmName}品牌吗?`" width="250px" icon="Delete" @confirm="removeTradeMark(row.id)">
              <template #reference>
                <el-button type="danger" icon="Delete"></el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
<!--      分页器组件-->
      <el-pagination
        v-model:current-page="pageNo"
        v-model:page-size="limit"
        :page-count="Math.ceil(total/limit)"
        :page-sizes="[3, 5, 7, 9]"
        :small="false"
        :background="true"
        layout="prev, pager, next, jumper,->,total, sizes, "
        :total="total"
        @current-change="getHasTrademark()"
        @size-change="sizeChange"
      />
    </el-card>
<!--  对话框组件:在添加品牌与修改已有品牌的业务时候使用该结构-->
  <el-dialog v-model="dialogFormVisible" :title="trademarkParams.id?'修改品牌':'添加品牌'">
      <el-form style="width: 80%;" :model="trademarkParams" :rules="rules" ref="formRef">
        <el-form-item label="品牌名称" label-width="100px" prop="tmName">
          <el-input placeholder="请您输入品牌名称" v-model="trademarkParams.tmName"></el-input>
        </el-form-item>
        <el-form-item label="品牌LOGO" label-width="100px" v-model="trademarkParams.logoUrl" prop="logoUrl">
          <el-upload
            class="avatar-uploader"
            action="/api/admin/product/fileUpload"
            :show-file-list="false"
            :on-success="handleAvatarSuccess"
            :before-upload="beforeAvatarUpload"
          >
            <img v-if="trademarkParams.logoUrl" :src="trademarkParams.logoUrl" class="avatar" />
            <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
          </el-upload>
        </el-form-item>
      </el-form>
<!--    具名插槽:footer-->
    <template #footer>
      <el-button size="default" type="primary" @click="cancel">取消</el-button>
      <el-button size="default" type="primary" @click="confirm">确定</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">

import { onMounted, reactive, ref } from 'vue'
import {reqHasTrademark,reqAddOrUpdateTrademark,reqDeleteTrademark} from '@/api/product/trademark'
import type {Records,TrademarkResponseData,Trademark} from '@/api/product/trademark/type.ts'
import { ElMessage, UploadProps } from 'element-plus'
// 分页器当前的页码
let pageNo = ref<number>(1)
// 每页展示多少条数据
let limit = ref<number>(3)
// 存储已有品牌数据的总数
let total = ref<number>(0)
// 存储已有品牌的数据
let trademarkArr = ref<Records>([])
// 控制对话框的显示与隐藏
let dialogFormVisible = ref<boolean>(false)
// 定义收集新增品牌数据
let trademarkParams = reactive<Trademark>({
  tmName:'',
  logoUrl:''
})
// 获取el-form组件实例
let formRef = ref()
// 获取已有品牌的接口封装成一个函数,在任何情况下获取数据,调用函数即可
const getHasTrademark = async () => {
  let result:TrademarkResponseData = await reqHasTrademark(pageNo.value,limit.value)
  //@ts-ignore
  if(result.code==200){
    // 存储已有品牌的总条数
    total.value = result.data.total
    trademarkArr.value = result.data.records
  }
}
// 组件挂载完毕--发送一次请求,获取第一页,一页三个已有品牌数据
onMounted(() => {
  getHasTrademark()
})
// 当下拉菜单发生变化的时候触发此方法
let sizeChange = () => {
  pageNo.value = 1
  getHasTrademark()
}
// 添加品牌回调
let addTrademark = () => {
  // 清空数据情况
  trademarkParams.id = 0
  trademarkParams.logoUrl = ''
  trademarkParams.tmName = ''
  dialogFormVisible.value = true
  // 清空校验规则提示错误信息
  formRef.value?.clearValidate('tmName')
  formRef.value?.clearValidate('logoUrl')
}
// 修改品牌回调
let updateTrademark = (row:Trademark) => {
  // 清空校验规则提示错误信息
  formRef.value?.clearValidate('tmName')
  formRef.value?.clearValidate('logoUrl')
  dialogFormVisible.value = true
  // ES6语法合并对象
  Object.assign(trademarkParams,row)
}

// 对话框底部取消按钮
let cancel = () => {
  // 对话框隐藏
  dialogFormVisible.value = false
}
// 对话框底部确定按钮
let confirm = async () => {
  // 在发请求之前,要对于整个表单进行校验
  await formRef.value.validate()
  let result = await reqAddOrUpdateTrademark(trademarkParams)
  // 添加|修改品牌
  if(result.code==200){
    // 添加品牌成功
    // 对话框隐藏
    dialogFormVisible.value = false
    // 弹出提示信息
    ElMessage({
      type:'success',
      message:trademarkParams.id?'修改品牌成功':'添加品牌成功'
    })
    // 再次发送请求获取已有全部品牌的数据
    await getHasTrademark()
  }else {
    // 添加品牌失败
    ElMessage({
      type:'error',
      message:trademarkParams.id?'修改品牌失败':'添加品牌失败'
    })
    // 对话框隐藏
    dialogFormVisible.value = false
  }
}
// 上传图片组件-上传图片之前触发的钩子函数
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  if (rawFile.type === 'image/jpeg' || rawFile.type == 'image/png' || rawFile.type == 'image/gif') {
    if(rawFile.size/1024/1024<4){
      return true
    }else {
      ElMessage({
        type:'error',
        message:'上传文件的大小应该小于4M'
      })
    }
  } else{
    ElMessage({
      type:'error',
      message:'上传文件格式务必是PNG|JPG|GIF'
    })
    return false
  }
}
// 图片上传成功的钩子
// @ts-ignore
const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
  // 收集上传图片的地址
  trademarkParams.logoUrl = response.data
  formRef.value.clearValidate('logoUrl')
}

// 品牌自定义校验规则的方法
// @ts-ignore
let validatorTmName = (rule:any,value:any,callBack:any) => {
  if(value.trim().length>=2){
    callBack()
  }else {
    callBack(new Error('品牌的名称位数需大于等于两位'))
  }
}
// 品牌logo自定义校验规则方法
// @ts-ignore
let validatorLogoName = (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:validatorLogoName}
  ]
}
// 删除气泡确认框按钮的回调
let removeTradeMark = async (id:number) => {
  // 点击确定按钮删除已有品牌id
  let result = await reqDeleteTrademark(id)
  if(result.code==200){
    // 删除成功提示信息
    ElMessage({
      type:'success',
      message:'删除品牌成功'
    })
    await getHasTrademark()
  }else{
    ElMessage({
      type:'error',
      message:'删除品牌失败'
    })
  }
}
</script>
<style scoped>
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

<style>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>

TS数据类型限制

export interface ResponseData{
  code:number,
  message:string,
  ok:boolean
}

// 已有品牌的ts数据类型
export interface Trademark{
  id?:number,
  tmName:string,
  logoUrl:string
}

// 包含全部品牌的ts数据类型
export type Records = Trademark[]


// 获取已有全部品牌的数据ts类型
export interface TrademarkResponseData extends ResponseData{
  data:{
    records:Records,
    total:number,
    size:number,
    current:number,
    searchCount:boolean,
    pages:number
  }
}

API接口封装

// 书写品牌管理模块接口
//@ts-ignore
import request from '@/utils/request.ts'
import type {TrademarkResponseData,Trademark} from '@/api/product/trademark/type.ts'

// 品牌管理模块接口地址
enum API{
  // 获取已有品牌的接口
  TRADEMARK_URL = "/admin/product/baseTrademark/",
  // 新增品牌接口
  ADDTRADEMARK_URL = '/admin/product/baseTrademark/save',
  // 修改已有品牌的接口
  UPDATETRADEMARK_URL = '/admin/product/baseTrademark/update',
  // 删除已有的品牌
  DELETETRADEMARK_URL = '/admin/product/baseTrademark/remove/'
}

// 获取已有品牌的接口方法
// page:获取第几页 -- 默认第一页
// limit:获取几个已有品牌的数据
export const reqHasTrademark = (page:number,limit:number) => request.get<any,TrademarkResponseData>(API.TRADEMARK_URL+`${page}/${limit}`)

// 新增与修改品牌接口
export const reqAddOrUpdateTrademark = (data:Trademark) => {
  if(data.id){
    // 修改已有品牌的id
    return request.put<any,any>(API.UPDATETRADEMARK_URL,data)
  }else {
    // 新增已有品牌
    return request.post<any,any>(API.ADDTRADEMARK_URL,data)
  }
}

// 删除某一个品牌的数据
export const reqDeleteTrademark = (id:number) => request.delete<any,any>(API.DELETETRADEMARK_URL+id)
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值