品牌管理页面搭建
<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
}
export interface Trademark{
id?:number,
tmName:string,
logoUrl:string
}
export type Records = Trademark[]
export interface TrademarkResponseData extends ResponseData{
data:{
records:Records,
total:number,
size:number,
current:number,
searchCount:boolean,
pages:number
}
}
API接口封装
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/'
}
export const reqHasTrademark = (page:number,limit:number) => request.get<any,TrademarkResponseData>(API.TRADEMARK_URL+`${page}/${limit}`)
export const reqAddOrUpdateTrademark = (data:Trademark) => {
if(data.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)