vue3.2/Vite/Ts63: 完成更新已有的SPU业务
·
Yin灏
目录结构
└─src
└─views
└─product
└─spu
├─index.vue
├─skuform.vue
└─spuform.vue
完成 SPU 更新
src/views/product/spu/spuform.vue
<template>
<el-form label-width="100px">
<el-form-item label="SPU名称">
<el-input
placeholder="请输入SPU名称"
v-mode="SpuParams.spuName"
></el-input>
</el-form-item>
<el-form-item label="SPU品牌">
<el-select v-model="SpuParams.tmId">
<el-option
v-for="(item, index) in AllTradeMark"
:key="item.id"
:label="item.tmName"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="SPU描述">
<el-input
type="textarea"
placeholder="请输入SPU描述"
v-model="SpuParams.description"
></el-input>
</el-form-item>
<el-form-item label="SPU照片">
<el-upload
v-model:file-list="imgList"
action="/api/admin/product/fileUpload"
list-type="picture-card"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:before-upload="handleUpload"
></el-upload>
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" style="width: 100%" alt="" />
</el-dialog>
</el-form-item>
<el-form-item label="SPU销售属性">
<!-- 展示销售属性 -->
<el-select
:placeholder="unSelectSaleAttr.length ? `还未选择${unSelectSaleAttr.length}个` : '无'"
v-model="saleAttrIdAndValueName"
>
<el-option
v-for="(item, index) in unSelectSaleAttr"
:key="item.id"
:label="item.name"
:value="`${item.id}:${item.name}`"
></el-option>
</el-select>
<el-button
type="primary"
size="default"
icon="Plus"
:disabled="saleAttrIdAndValueName ? false : true"
@click="addSaleAttr"
>添加属性</el-button
>
<!-- 展示销售属性与属性值 -->
<el-table border :data="saleAttr">
<el-table-column
label="序号"
type="index"
width="80px"
align
></el-table-column>
<el-table-column
label="销售属性名字"
width="100px"
prop="saleAttrName"
></el-table-column>
<el-table-column label="销售属性值">
<template #="{ row, $index }">
<el-tag
v-for="(item, index) in row.spuSaleAttrValueList"
:key="row.id"
class="mx-1"
closable
@close="row.spuSaleAttrValueList.splice($index, 1)"
>{{ item.saleAttrValueName }}</el-tag
>
<el-input
placeholder="请你输入属性值"
size="small"
style="width: 100px"
v-if="row.flag === true"
v-model="row.saleAttrValue"
@blur="toLook(row)"
></el-input>
<el-button
v-else
type="primary"
size="small"
icon="Plus"
@click="toEdit(row)"
></el-button>
</template>
</el-table-column>
<el-table-column label="操作" width="120px">
<template #="{row, $index}">
<el-button
type="primary"
size="small"
icon="Delete"
@click="saleAttr.splice($index, 1)"
></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="default"
@click="save"
:disabled="saleAttr.length > 0 ? false : true"
>保存</el-button
>
<el-button type="primary" size="default" @click="cancel">取消</el-button>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { ref, computed } from "vue";
//...
import type {
SpuData,
AllTradeMark,
SpuHasImg,
SaleAttrResponseData,
HasSaleAttrResponseData,
Trademark,
SpuImage,
SaleAttr,
HasSaleAttr,
SaleAttrValue
} from "@/api/product/spu/type";
import {
reqAllTradeMark,
reqSpuImageList,
reqSpuHasSaleAttr,
reqAllSaleAttr,
reqAddOrUpdateSpu
} from "@/api/product/spu";
//...
let dialogVisible = ref<boolean>(false);
let dialogImageUrl = ref<string>('');
let AllTradeMark = ref<Trademark>([]);
let imgList = ref<SpuImage>([]);
let saleAttr = ref<SaleAttr>([]);
let allSaleAttr = ref<HasSaleAttr>([]);
let saleAttrIdAndValueName = ref<string>('');
let SpuParams = ref<SpuData>({
category3Id: '';
spuName: '';
tmId: '';
description: '';
spuImageList: [];
spuSaleAttrList: [];
});
//...
const initHasSpuData = async (spu: SpuData) => {
SpuParams.value = SpuData;
const result: AllTradeMark = await reqAllTradeMark();
const result1: SpuHasImg = await reqSpuImageList(spu.id as number);
const result2: SaleAttrResponseData = await reqSpuHasSaleAttr(
spu.id as number
);
const result3: HasSaleAttrResponseData = await reqAllSaleAttr();
// 数据存储
AllTradeMark.value = result.data;
imgList.value = result1.data.map(item => {
return {
name: item.imgName,
url: item.imgUrl
}
});
saleAttr.value = result2.data;
allSaleAttr.value = result3.data;
};
defineExpose({ initHasSpuData });
const handlePictureCardPreview = (file: any) => {
dialogImageUrl.value = file.url;
dialogVisible.value = true;
}
const handleRemove = () => {}
const handleUpload = (file: any) => {
if(file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/gif') {
if(file.size / 1024 / 1024 < 3) {
return true
} else {
ElMessage({
type: 'error',
message: '上传图片要小于3M'
})
return false;
}
} else {
ElMessage({
type: 'error',
message: '只能上传图片类型'
})
return false
}
}
let unSelectSaleAttr = computed(() => {
let unSelectArr = allSaleAttr.value.filter(item => {
return saleAttr.value.every(item1 => {
return item.name !== item1.saleAttrName
})
});
return unSelectArr;
})
let addSaleAttr = () => {
const [baseSaleAttrId, saleAttrName] = saleAttrIdAndValueName.value.split(':');
let newSaleAttr: SaleAttr = {
baseSaleAttrId,
saleAttrName,
spuSaleAttrValueList: []
};
saleAttr.value.push(newSaleAttr);
saleAttrIdAndValueName.value = '';
}
const toEdit = (row: SaleAttr) => {
row.flag = true;
row.saleAttrValue = '';
}
const toLook = (row: SaleAttr) => {
const {
baseSaleAttrId,
saleAttrValue
} = row;
let newSaleAttrValue: SaleAttrValue = {
baseSaleAttrId,
saleAttrValueName: (saleAttrValue as string)
}
if((saleAttrValue as string).trim() === '') {
ElMessage({
type: 'error',
message: '属性值不能为空'
})
return;
}
let repeat = row.spuSaleAttrValueList.find(item => {
return item.saleAttrValueName === saleAttrValue;
})
if(repeat) {
ElMessage({
type: 'error',
message: '属性值不能重复'
})
return;
}
row.spuSaleAttrValueList.push(newSaleAttrValue);
row.flag = false;
}
const save = async () => {
SpuParams.value.spuImageList = imgList.value.map((item: any) => {
return {
imgName: item.name,
imgUrl: (item.response && item.response.data) || item.url
}
});
SpuParams.value.spuSaleAttrList = saleAttr.value;
const result: any = await reqAddOrUpdateSpu(SpuParams.value);
if(result.code === 200) {
ElMessage({
type: 'success',
message: SpuParams.id ? '更新成功' : '添加成功'
});
$emit('changeScene', 0)
} else {
ElMessage({
type: 'error',
message: SpuParams.id ? '更新失败' : '添加失败'
})
}
}
</script>
父组件重新获取 SPU
SPU 场景切换
src/views/product/spu/index.vue
<template>
<!-- .... -->
</template>
<script setup lang="ts">
//...
const getHasSpu = async (paper = 1) => {
pageNo.value = paper;
const result: HasSpuResponseData = await reqHasSpu(
pageNo.value,
pageSize.value,
categoryStore.c3Id
);
if (result.code === 200) {
records.value = result.data.records;
total.value = result.data.total;
}
};
//...
const changeScene = (num: number) => {
scene.value = num;
getHasSpu();
};
//...
</script>