Skip to content

Commit e0a731d

Browse files
committed
商品评论、优惠券模板复用组件【商品橱窗】
1 parent 3198688 commit e0a731d

File tree

4 files changed

+41
-101
lines changed

4 files changed

+41
-101
lines changed

src/views/mall/product/comment/CommentForm.vue

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,7 @@
88
v-loading="formLoading"
99
>
1010
<el-form-item label="商品" prop="spuId">
11-
<div @click="handleSelectSpu" class="h-60px w-60px">
12-
<div v-if="spuData && spuData.picUrl">
13-
<el-image :src="spuData.picUrl" />
14-
</div>
15-
<div v-else class="select-box">
16-
<Icon icon="ep:plus" />
17-
</div>
18-
</div>
11+
<SpuShowcase v-model="formData.spuId" :limit="1" />
1912
</el-form-item>
2013
<el-form-item label="商品规格" prop="skuId" v-if="formData.spuId">
2114
<div @click="handleSelectSku" class="h-60px w-60px">
@@ -51,12 +44,11 @@
5144
<el-button @click="dialogVisible = false">取 消</el-button>
5245
</template>
5346
</Dialog>
54-
<SpuTableSelect ref="spuTableSelectRef" @change="handleSpuChange" />
55-
<SkuTableSelect ref="skuTableSelectRef" @change="handleSkuChange" :spu-id="spuData.id" />
47+
<SkuTableSelect ref="skuTableSelectRef" @change="handleSkuChange" :spu-id="formData.spuId" />
5648
</template>
5749
<script setup lang="ts">
5850
import * as CommentApi from '@/api/mall/product/comment'
59-
import SpuTableSelect from '@/views/mall/product/spu/components/SpuTableSelect.vue'
51+
import SpuShowcase from "@/views/mall/product/spu/components/SpuShowcase.vue";
6052
import * as ProductSpuApi from '@/api/mall/product/spu'
6153
import SkuTableSelect from '@/views/mall/product/spu/components/SkuTableSelect.vue'
6254
@@ -72,8 +64,7 @@ const formData = ref({
7264
userId: undefined,
7365
userNickname: undefined,
7466
userAvatar: undefined,
75-
spuId: undefined,
76-
spuName: undefined,
67+
spuId: 0,
7768
skuId: undefined,
7869
descriptionScores: 5,
7970
benefitScores: 5,
@@ -90,7 +81,6 @@ const formRules = reactive({
9081
benefitScores: [{ required: true, message: '服务星级不能为空', trigger: 'blur' }]
9182
})
9283
const formRef = ref() // 表单 Ref
93-
const spuData = ref<ProductSpuApi.Spu>({})
9484
const skuData = ref({
9585
id: -1,
9686
name: '',
@@ -149,8 +139,7 @@ const resetForm = () => {
149139
userId: undefined,
150140
userNickname: undefined,
151141
userAvatar: undefined,
152-
spuId: undefined,
153-
spuName: undefined,
142+
spuId: 0,
154143
skuId: undefined,
155144
descriptionScores: 5,
156145
benefitScores: 5,
@@ -160,16 +149,6 @@ const resetForm = () => {
160149
formRef.value?.resetFields()
161150
}
162151
163-
/** SPU 表格选择 */
164-
const spuTableSelectRef = ref()
165-
const handleSelectSpu = () => {
166-
spuTableSelectRef.value.open()
167-
}
168-
const handleSpuChange = (spu: ProductSpuApi.Spu) => {
169-
spuData.value = spu
170-
formData.value.spuId = spu.id
171-
}
172-
173152
/** SKU 表格选择 */
174153
const skuTableSelectRef = ref()
175154
const handleSelectSku = () => {

src/views/mall/product/comment/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
<!-- 列表 -->
6060
<ContentWrap>
6161
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="false">
62-
<el-table-column label="评论编号" align="center" prop="id" min-width="50" />
62+
<el-table-column label="评论编号" align="center" prop="id" min-width="80" />
6363
<el-table-column label="商品信息" align="center" min-width="400">
6464
<template #default="scope">
6565
<div class="row flex items-center gap-x-4px">

src/views/mall/product/spu/components/SpuShowcase.vue

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,8 @@
1313
</div>
1414
</el-tooltip>
1515
</div>
16-
<el-tooltip content="选择商品">
17-
<div
18-
v-show="!disabled"
19-
v-if="!limit || limit <= productSpus.length"
20-
class="select-box"
21-
@click="openSpuTableSelect"
22-
>
16+
<el-tooltip content="选择商品" v-if="canAdd">
17+
<div class="select-box" @click="openSpuTableSelect">
2318
<Icon icon="ep:plus" />
2419
</div>
2520
</el-tooltip>
@@ -31,35 +26,52 @@
3126
import * as ProductSpuApi from '@/api/mall/product/spu'
3227
import SpuTableSelect from '@/views/mall/product/spu/components/SpuTableSelect.vue'
3328
import { propTypes } from '@/utils/propTypes'
34-
import { array } from 'vue-types'
29+
import { oneOfType } from 'vue-types'
30+
import { isArray } from "@/utils/is";
3531
3632
// 商品橱窗,一般用于与商品建立关系时使用
3733
// 提供功能:展示商品列表、添加商品、移除商品
3834
defineOptions({ name: 'SpuShowcase' })
3935
4036
const props = defineProps({
41-
modelValue: array<number>().def([]).isRequired,
37+
modelValue: oneOfType<number | Array<number>>([Number, Array]).isRequired,
4238
// 限制数量:默认不限制
43-
limit: propTypes.number.def(0),
39+
limit: propTypes.number.def(Number.MAX_VALUE),
4440
disabled: propTypes.bool.def(false)
4541
})
4642
43+
// 计算是否可以添加
44+
const canAdd = computed(() => {
45+
// 情况一:禁用时不可以添加
46+
if(props.disabled) return false
47+
// 情况二:未指定限制数量时,可以添加
48+
if(!props.limit) return true
49+
// 情况三:检查已添加数量是否小于限制数量
50+
return productSpus.value.length < props.limit
51+
})
52+
4753
// 商品列表
4854
const productSpus = ref<ProductSpuApi.Spu[]>([])
4955
5056
watch(
5157
() => props.modelValue,
5258
async () => {
53-
if (props.modelValue.length === 0) {
59+
const ids = isArray(props.modelValue)
60+
// 情况一:多选
61+
? props.modelValue
62+
// 情况二:单选
63+
: props.modelValue ? [props.modelValue]: []
64+
// 不需要返显
65+
if(ids.length === 0) {
5466
productSpus.value = []
5567
return
5668
}
5769
// 只有商品发生变化之后,才去查询商品
5870
if (
5971
productSpus.value.length === 0 ||
60-
productSpus.value.some((spu) => !props.modelValue.includes(spu.id))
72+
productSpus.value.some((spu) => !ids.includes(spu.id!))
6173
) {
62-
productSpus.value = await ProductSpuApi.getSpuDetailList(props.modelValue)
74+
productSpus.value = await ProductSpuApi.getSpuDetailList(ids)
6375
}
6476
},
6577
{ immediate: true }
@@ -91,11 +103,14 @@ const handleRemoveSpu = (index: number) => {
91103
}
92104
const emit = defineEmits(['update:modelValue', 'change'])
93105
const emitSpuChange = () => {
94-
emit(
95-
'update:modelValue',
96-
productSpus.value.map((spu) => spu.id)
97-
)
98-
emit('change', productSpus.value)
106+
if(props.limit === 1) {
107+
const spu = productSpus.value.length > 0 ? productSpus.value[0] : null
108+
emit('update:modelValue', spu?.id || 0)
109+
emit('change', spu)
110+
} else {
111+
emit('update:modelValue', productSpus.value.map((spu) => spu.id))
112+
emit('change', productSpus.value)
113+
}
99114
}
100115
</script>
101116

src/views/mall/promotion/coupon/template/CouponTemplateForm.vue

Lines changed: 2 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,7 @@
2626
label="商品"
2727
prop="productSpuIds"
2828
>
29-
<div class="flex flex-wrap items-center gap-1">
30-
<div v-for="(spu, index) in productSpus" :key="spu.id" class="select-box spu-pic">
31-
<el-image :src="spu.picUrl" />
32-
<Icon class="del-icon" icon="ep:circle-close-filled" @click="handleRemoveSpu(index)" />
33-
</div>
34-
<div class="select-box" @click="openSpuTableSelect">
35-
<Icon icon="ep:plus" />
36-
</div>
37-
</div>
29+
<SpuShowcase v-model="formData.productSpuIds" />
3830
</el-form-item>
3931
<el-form-item
4032
v-if="formData.productScope === PromotionProductScopeEnum.CATEGORY.scope"
@@ -186,18 +178,16 @@
186178
<el-button @click="dialogVisible = false">取 消</el-button>
187179
</template>
188180
</Dialog>
189-
<SpuTableSelect ref="spuTableSelectRef" multiple @change="handleSpuSelected" />
190181
</template>
191182
<script lang="ts" setup>
192183
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
193184
import * as CouponTemplateApi from '@/api/mall/promotion/coupon/couponTemplate'
194-
import * as ProductSpuApi from '@/api/mall/product/spu'
195185
import {
196186
CouponTemplateValidityTypeEnum,
197187
PromotionDiscountTypeEnum,
198188
PromotionProductScopeEnum
199189
} from '@/utils/constants'
200-
import SpuTableSelect from '@/views/mall/product/spu/components/SpuTableSelect.vue'
190+
import SpuShowcase from "@/views/mall/product/spu/components/SpuShowcase.vue";
201191
import ProductCategorySelect from '@/views/mall/product/category/components/ProductCategorySelect.vue'
202192
import { convertToInteger, formatToFraction } from '@/utils'
203193
@@ -251,7 +241,6 @@ const formRules = reactive({
251241
productCategoryIds: [{ required: true, message: '分类不能为空', trigger: 'blur' }]
252242
})
253243
const formRef = ref() // 表单 Ref
254-
const productSpus = ref<ProductSpuApi.Spu[]>([]) // 商品列表
255244
256245
/** 打开弹窗 */
257246
const open = async (type: string, id?: number) => {
@@ -354,7 +343,6 @@ const resetForm = () => {
354343
productCategoryIds: []
355344
}
356345
formRef.value?.resetFields()
357-
productSpus.value = []
358346
}
359347
360348
/** 获得商品范围 */
@@ -363,8 +351,6 @@ const getProductScope = async () => {
363351
case PromotionProductScopeEnum.SPU.scope:
364352
// 设置商品编号
365353
formData.value.productSpuIds = formData.value.productScopeValues
366-
// 获得商品列表
367-
productSpus.value = await ProductSpuApi.getSpuDetailList(formData.value.productScopeValues)
368354
break
369355
case PromotionProductScopeEnum.CATEGORY.scope:
370356
await nextTick(() => {
@@ -397,47 +383,7 @@ function setProductScopeValues(data: CouponTemplateApi.CouponTemplateVO) {
397383
break
398384
}
399385
}
400-
401-
/** 活动商品的按钮 */
402-
const spuTableSelectRef = ref()
403-
const openSpuTableSelect = () => {
404-
spuTableSelectRef.value.open(productSpus.value)
405-
}
406-
407-
/** 选择商品后触发 */
408-
const handleSpuSelected = (spus: ProductSpuApi.Spu[]) => {
409-
productSpus.value = spus
410-
formData.value.productSpuIds = spus.map((spu) => spu.id) as []
411-
}
412-
413-
/** 选择商品后触发 */
414-
const handleRemoveSpu = (index: number) => {
415-
productSpus.value.splice(index, 1)
416-
formData.value.productSpuIds.splice(index, 1)
417-
}
418386
</script>
419387

420388
<style lang="scss" scoped>
421-
.select-box {
422-
display: flex;
423-
width: 60px;
424-
height: 60px;
425-
border: 1px dashed var(--el-border-color-darker);
426-
border-radius: 8px;
427-
align-items: center;
428-
justify-content: center;
429-
}
430-
431-
.spu-pic {
432-
position: relative;
433-
}
434-
435-
.del-icon {
436-
position: absolute;
437-
top: -10px;
438-
right: -10px;
439-
z-index: 1;
440-
width: 20px !important;
441-
height: 20px !important;
442-
}
443389
</style>

0 commit comments

Comments
 (0)