Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
38545e89
authored
May 20, 2023
by
puhui999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 优化相关逻辑,修复遗留bug
parent
0c42b76a
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
76 additions
and
51 deletions
+76
-51
src/views/mall/product/spu/addForm.vue
+1
-21
src/views/mall/product/spu/components/BasicInfoForm.vue
+28
-12
src/views/mall/product/spu/components/ProductAttributes.vue
+25
-11
src/views/mall/product/spu/components/ProductAttributesAddForm.vue
+20
-3
src/views/mall/product/spu/components/SkuList.vue
+2
-4
No files found.
src/views/mall/product/spu/addForm.vue
View file @
38545e89
...
@@ -37,7 +37,6 @@ import { useTagsViewStore } from '@/store/modules/tagsView'
...
@@ -37,7 +37,6 @@ import { useTagsViewStore } from '@/store/modules/tagsView'
import
{
BasicInfoForm
,
DescriptionForm
,
OtherSettingsForm
}
from
'./components'
import
{
BasicInfoForm
,
DescriptionForm
,
OtherSettingsForm
}
from
'./components'
// 业务api
// 业务api
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
PropertyApi
from
'@/api/mall/product/property'
import
{
convertToInteger
,
formatToFraction
}
from
'@/utils'
import
{
convertToInteger
,
formatToFraction
}
from
'@/utils'
const
{
t
}
=
useI18n
()
// 国际化
const
{
t
}
=
useI18n
()
// 国际化
...
@@ -105,25 +104,6 @@ const getDetail = async () => {
...
@@ -105,25 +104,6 @@ const getDetail = async () => {
item
.
subCommissionSecondPrice
=
formatToFraction
(
item
.
subCommissionSecondPrice
)
item
.
subCommissionSecondPrice
=
formatToFraction
(
item
.
subCommissionSecondPrice
)
})
})
formData
.
value
=
res
formData
.
value
=
res
// 只有是多规格才处理
if
(
res
.
specType
)
{
// TODO @puhui999:可以直接拿 propertyName 拼接处规格 id + 属性,可以看下商品 uniapp 详情的做法
// fix: 考虑到 sku 数量和通过属性算出来的sku不一致的情况
const
propertyIds
=
[]
res
.
skus
.
forEach
((
sku
)
=>
sku
.
properties
?.
map
((
property
)
=>
property
.
propertyId
)
.
forEach
((
propertyId
)
=>
{
if
(
propertyIds
.
indexOf
(
propertyId
)
===
-
1
)
{
propertyIds
.
push
(
propertyId
)
}
})
)
const
properties
=
await
PropertyApi
.
getPropertyListAndValue
({
propertyIds
})
await
nextTick
()
// 回显商品属性
basicInfoRef
.
value
.
addAttribute
(
properties
)
}
}
finally
{
}
finally
{
formLoading
.
value
=
false
formLoading
.
value
=
false
}
}
...
@@ -141,7 +121,7 @@ const submitForm = async () => {
...
@@ -141,7 +121,7 @@ const submitForm = async () => {
await
unref
(
descriptionRef
)?.
validate
()
await
unref
(
descriptionRef
)?.
validate
()
await
unref
(
otherSettingsRef
)?.
validate
()
await
unref
(
otherSettingsRef
)?.
validate
()
const
deepCopyFormData
=
cloneDeep
(
unref
(
formData
.
value
))
// 深拷贝一份 fix:这样最终 server 端不满足,不需要恢复,
const
deepCopyFormData
=
cloneDeep
(
unref
(
formData
.
value
))
// 深拷贝一份 fix:这样最终 server 端不满足,不需要恢复,
// TODO 兜底处理 sku 空数据
详见 SkuList TODO
// TODO 兜底处理 sku 空数据
formData
.
value
.
skus
.
forEach
((
sku
)
=>
{
formData
.
value
.
skus
.
forEach
((
sku
)
=>
{
// 因为是空数据这里判断一下商品条码是否为空就行
// 因为是空数据这里判断一下商品条码是否为空就行
if
(
sku
.
barCode
===
''
)
{
if
(
sku
.
barCode
===
''
)
{
...
...
src/views/mall/product/spu/components/BasicInfoForm.vue
View file @
38545e89
...
@@ -98,14 +98,14 @@
...
@@ -98,14 +98,14 @@
<el-form-item
v-if=
"formData.specType"
label=
"商品属性"
>
<el-form-item
v-if=
"formData.specType"
label=
"商品属性"
>
<!-- TODO @puhui999:参考 https://admin.java.crmeb.net/store/list/creatProduct 添加规格好做么?添加的时候,不用输入备注哈 fix-->
<!-- TODO @puhui999:参考 https://admin.java.crmeb.net/store/list/creatProduct 添加规格好做么?添加的时候,不用输入备注哈 fix-->
<el-button
class=
"mr-15px mb-10px"
@
click=
"attributesAddFormRef.open"
>
添加规格
</el-button>
<el-button
class=
"mr-15px mb-10px"
@
click=
"attributesAddFormRef.open"
>
添加规格
</el-button>
<ProductAttributes
:propertyList=
"propertyList"
/>
<ProductAttributes
:propertyList=
"propertyList"
@
success=
"generateSkus"
/>
</el-form-item>
</el-form-item>
<template
v-if=
"formData.specType && propertyList.length > 0"
>
<template
v-if=
"formData.specType && propertyList.length > 0"
>
<el-form-item
label=
"批量设置"
>
<el-form-item
label=
"批量设置"
>
<SkuList
:is-batch=
"true"
:prop-form-data=
"formData"
:propertyList=
"propertyList"
/>
<SkuList
:is-batch=
"true"
:prop-form-data=
"formData"
:propertyList=
"propertyList"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"属性列表"
>
<el-form-item
label=
"属性列表"
>
<SkuList
:prop-form-data=
"formData"
:propertyList=
"propertyList"
/>
<SkuList
ref=
"skuListRef"
:prop-form-data=
"formData"
:propertyList=
"propertyList"
/>
</el-form-item>
</el-form-item>
</
template
>
</
template
>
<el-form-item
v-if=
"!formData.specType"
>
<el-form-item
v-if=
"!formData.specType"
>
...
@@ -114,7 +114,7 @@
...
@@ -114,7 +114,7 @@
</el-col>
</el-col>
</el-row>
</el-row>
</el-form>
</el-form>
<ProductAttributesAddForm
ref=
"attributesAddFormRef"
@
success=
"addAttribute
"
/>
<ProductAttributesAddForm
ref=
"attributesAddFormRef"
:propertyList=
"propertyList
"
/>
</template>
</template>
<
script
lang=
"ts"
name=
"ProductSpuBasicInfoForm"
setup
>
<
script
lang=
"ts"
name=
"ProductSpuBasicInfoForm"
setup
>
import
{
PropType
}
from
'vue'
import
{
PropType
}
from
'vue'
...
@@ -141,15 +141,11 @@ const attributesAddFormRef = ref() // 添加商品属性表单 TODO @puhui999:
...
@@ -141,15 +141,11 @@ const attributesAddFormRef = ref() // 添加商品属性表单 TODO @puhui999:
const
productSpuBasicInfoRef
=
ref
()
// 表单Ref TODO @puhui999:小写开头哈 fix
const
productSpuBasicInfoRef
=
ref
()
// 表单Ref TODO @puhui999:小写开头哈 fix
// TODO @puhui999:attributeList 改成 propertyList,会更统一一点 fix
// TODO @puhui999:attributeList 改成 propertyList,会更统一一点 fix
const
propertyList
=
ref
([])
// 商品属性列表
const
propertyList
=
ref
([])
// 商品属性列表
/** 添加商品属性 */
const
skuListRef
=
ref
()
// 商品属性列表Ref
// TODO @puhui999:propFormData 算出来 fix: 因为ProductAttributesAddForm添加属性成功回调得使用不能完全依赖于propFormData
const
addAttribute
=
(
property
:
any
)
=>
{
Array
.
isArray
(
property
)
?
(
propertyList
.
value
=
property
)
:
propertyList
.
value
.
push
(
property
)
}
/** 调用 SkuList generateTableData 方法*/
/** 调用 SkuList generateTableData 方法*/
// const generateSkus(propertyList)
{
const
generateSkus
=
(
propertyList
)
=>
{
// skuList.value.generateTableData(
)
skuListRef
.
value
.
generateTableData
(
propertyList
)
//
}
}
const
formData
=
reactive
<
SpuType
>
({
const
formData
=
reactive
<
SpuType
>
({
name
:
''
,
// 商品名称
name
:
''
,
// 商品名称
categoryId
:
null
,
// 商品分类
categoryId
:
null
,
// 商品分类
...
@@ -191,6 +187,26 @@ watch(
...
@@ -191,6 +187,26 @@ watch(
formData
.
sliderPicUrls
=
data
[
'sliderPicUrls'
].
map
((
item
)
=>
({
formData
.
sliderPicUrls
=
data
[
'sliderPicUrls'
].
map
((
item
)
=>
({
url
:
item
url
:
item
}))
}))
// 只有是多规格才处理
if
(
formData
.
specType
)
{
// TODO @puhui999:可以直接拿 propertyName 拼接处规格 id + 属性,可以看下商品 uniapp 详情的做法
// fix: 直接拿返回的 skus 属性逆向生成出 propertyList
const
properties
=
[]
formData
.
skus
.
forEach
((
sku
)
=>
{
sku
.
properties
.
forEach
(({
propertyId
,
propertyName
,
valueId
,
valueName
})
=>
{
// 添加属性
if
(
!
properties
.
some
((
item
)
=>
item
.
id
===
propertyId
))
{
properties
.
push
({
id
:
propertyId
,
name
:
propertyName
,
values
:
[]
})
}
// 添加属性值
const
index
=
properties
.
findIndex
((
item
)
=>
item
.
id
===
propertyId
)
if
(
!
properties
[
index
].
values
.
some
((
value
)
=>
value
.
id
===
valueId
))
{
properties
[
index
].
values
.
push
({
id
:
valueId
,
name
:
valueName
})
}
})
})
propertyList
.
value
=
properties
}
},
},
{
{
// fix: 去掉深度监听只有对象引用发生改变的时候才执行,解决改一动多的问题
// fix: 去掉深度监听只有对象引用发生改变的时候才执行,解决改一动多的问题
...
@@ -217,7 +233,7 @@ const validate = async () => {
...
@@ -217,7 +233,7 @@ const validate = async () => {
}
}
})
})
}
}
defineExpose
({
validate
,
addAttribute
})
defineExpose
({
validate
})
/** 分销类型 */
/** 分销类型 */
const
changeSubCommissionType
=
()
=>
{
const
changeSubCommissionType
=
()
=>
{
...
...
src/views/mall/product/spu/components/ProductAttributes.vue
View file @
38545e89
...
@@ -2,23 +2,25 @@
...
@@ -2,23 +2,25 @@
<el-col
v-for=
"(item, index) in attributeList"
:key=
"index"
>
<el-col
v-for=
"(item, index) in attributeList"
:key=
"index"
>
<div>
<div>
<el-text
class=
"mx-1"
>
属性名:
</el-text>
<el-text
class=
"mx-1"
>
属性名:
</el-text>
<el-text
class=
"mx-1"
>
{{
item
.
name
}}
</el-text>
<el-tag
class=
"mx-1"
closable
type=
"success"
@
close=
"handleCloseProperty(index)"
>
{{
item
.
name
}}
</el-tag>
</div>
</div>
<div>
<div>
<el-text
class=
"mx-1"
>
属性值:
</el-text>
<el-text
class=
"mx-1"
>
属性值:
</el-text>
<el-tag
<el-tag
v-for=
"(value, valueIndex) in item.values"
v-for=
"(value, valueIndex) in item.values"
:key=
"value.id"
:key=
"value.id"
:disable-transitions=
"false"
class=
"mx-1"
class=
"mx-1"
closable
closable
@
close=
"handleClose(index, valueIndex)"
@
close=
"handleClose
Value
(index, valueIndex)"
>
>
{{
value
.
name
}}
{{
value
.
name
}}
</el-tag>
</el-tag>
<el-input
<el-input
v-show=
"inputVisible(index)"
v-show=
"inputVisible(index)"
ref=
"InputRef"
:id=
"`input$
{index}`"
:ref="setInputRef"
v-model="inputValue"
v-model="inputValue"
class="!w-20"
class="!w-20"
size="small"
size="small"
...
@@ -51,7 +53,15 @@ const inputVisible = computed(() => (index) => {
...
@@ -51,7 +53,15 @@ const inputVisible = computed(() => (index) => {
if
(
attributeIndex
.
value
===
null
)
return
false
if
(
attributeIndex
.
value
===
null
)
return
false
if
(
attributeIndex
.
value
===
index
)
return
true
if
(
attributeIndex
.
value
===
index
)
return
true
})
})
const
InputRef
=
ref
()
//标签输入框Ref
const
inputRef
=
ref
([])
//标签输入框Ref
/** 解决 ref 在 v-for 中的获取问题*/
const
setInputRef
=
(
el
)
=>
{
if
(
el
===
null
||
typeof
el
===
'undefined'
)
return
// 如果不存在id相同的元素才添加
if
(
!
inputRef
.
value
.
some
((
item
)
=>
item
.
input
?.
attributes
.
id
===
el
.
input
?.
attributes
.
id
))
{
inputRef
.
value
.
push
(
el
)
}
}
const
attributeList
=
ref
([])
// 商品属性列表
const
attributeList
=
ref
([])
// 商品属性列表
const
props
=
defineProps
({
const
props
=
defineProps
({
propertyList
:
{
propertyList
:
{
...
@@ -72,19 +82,22 @@ watch(
...
@@ -72,19 +82,22 @@ watch(
}
}
)
)
/** 删除
标签 tagValue 标签
值*/
/** 删除
属性
值*/
const
handleClose
=
(
index
,
valueIndex
)
=>
{
const
handleClose
Value
=
(
index
,
valueIndex
)
=>
{
attributeList
.
value
[
index
].
values
?.
splice
(
valueIndex
,
1
)
attributeList
.
value
[
index
].
values
?.
splice
(
valueIndex
,
1
)
}
}
/** 删除属性*/
const
handleCloseProperty
=
(
index
)
=>
{
attributeList
.
value
?.
splice
(
index
,
1
)
}
/** 显示输入框并获取焦点 */
/** 显示输入框并获取焦点 */
const
showInput
=
async
(
index
)
=>
{
const
showInput
=
async
(
index
)
=>
{
attributeIndex
.
value
=
index
attributeIndex
.
value
=
index
// TODO 嗯!!!自动获取焦点还是有点问题,后续继续改进
inputRef
.
value
[
index
].
focus
()
// 因为组件在ref中所以需要用索引获取对应的Ref
InputRef
.
value
[
index
]
!
.
input
!
.
focus
()
}
}
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
/** 输入框失去焦点或点击回车时触发 */
/** 输入框失去焦点或点击回车时触发 */
const
handleInputConfirm
=
async
(
index
,
propertyId
)
=>
{
const
handleInputConfirm
=
async
(
index
,
propertyId
)
=>
{
if
(
inputValue
.
value
)
{
if
(
inputValue
.
value
)
{
...
@@ -93,6 +106,7 @@ const handleInputConfirm = async (index, propertyId) => {
...
@@ -93,6 +106,7 @@ const handleInputConfirm = async (index, propertyId) => {
const
id
=
await
PropertyApi
.
createPropertyValue
({
propertyId
,
name
:
inputValue
.
value
})
const
id
=
await
PropertyApi
.
createPropertyValue
({
propertyId
,
name
:
inputValue
.
value
})
attributeList
.
value
[
index
].
values
.
push
({
id
,
name
:
inputValue
.
value
})
attributeList
.
value
[
index
].
values
.
push
({
id
,
name
:
inputValue
.
value
})
message
.
success
(
t
(
'common.createSuccess'
))
message
.
success
(
t
(
'common.createSuccess'
))
emit
(
'success'
,
attributeList
.
value
)
}
catch
{
}
catch
{
message
.
error
(
'添加失败,请重试'
)
// TODO 缺少国际化
message
.
error
(
'添加失败,请重试'
)
// TODO 缺少国际化
}
}
...
...
src/views/mall/product/spu/components/ProductAttributesAddForm.vue
View file @
38545e89
...
@@ -33,7 +33,25 @@ const formRules = reactive({
...
@@ -33,7 +33,25 @@ const formRules = reactive({
name
:
[{
required
:
true
,
message
:
'名称不能为空'
,
trigger
:
'blur'
}]
name
:
[{
required
:
true
,
message
:
'名称不能为空'
,
trigger
:
'blur'
}]
})
})
const
formRef
=
ref
()
// 表单 Ref
const
formRef
=
ref
()
// 表单 Ref
const
attributeList
=
ref
([])
// 商品属性列表
const
props
=
defineProps
({
propertyList
:
{
type
:
Array
,
default
:
()
=>
{}
}
})
watch
(
()
=>
props
.
propertyList
,
(
data
)
=>
{
if
(
!
data
)
return
attributeList
.
value
=
data
},
{
deep
:
true
,
immediate
:
true
}
)
/** 打开弹窗 */
/** 打开弹窗 */
const
open
=
async
()
=>
{
const
open
=
async
()
=>
{
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
...
@@ -42,7 +60,6 @@ const open = async () => {
...
@@ -42,7 +60,6 @@ const open = async () => {
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
/** 提交表单 */
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
const
submitForm
=
async
()
=>
{
const
submitForm
=
async
()
=>
{
// 校验表单
// 校验表单
if
(
!
formRef
)
return
if
(
!
formRef
)
return
...
@@ -56,12 +73,12 @@ const submitForm = async () => {
...
@@ -56,12 +73,12 @@ const submitForm = async () => {
const
res
=
await
PropertyApi
.
getPropertyListAndValue
({
name
:
data
.
name
})
const
res
=
await
PropertyApi
.
getPropertyListAndValue
({
name
:
data
.
name
})
if
(
res
.
length
===
0
)
{
if
(
res
.
length
===
0
)
{
const
propertyId
=
await
PropertyApi
.
createProperty
(
data
)
const
propertyId
=
await
PropertyApi
.
createProperty
(
data
)
emit
(
'success'
,
{
id
:
propertyId
,
...
formData
.
value
,
values
:
[]
})
attributeList
.
value
.
push
(
{
id
:
propertyId
,
...
formData
.
value
,
values
:
[]
})
}
else
{
}
else
{
if
(
res
[
0
].
values
===
null
)
{
if
(
res
[
0
].
values
===
null
)
{
res
[
0
].
values
=
[]
res
[
0
].
values
=
[]
}
}
emit
(
'success'
,
res
[
0
])
// 因为只用一个
attributeList
.
value
.
push
(
res
[
0
])
// 因为只用一个
}
}
message
.
success
(
t
(
'common.createSuccess'
))
message
.
success
(
t
(
'common.createSuccess'
))
dialogVisible
.
value
=
false
dialogVisible
.
value
=
false
...
...
src/views/mall/product/spu/components/SkuList.vue
View file @
38545e89
...
@@ -212,10 +212,6 @@ const generateTableData = (propertyList: any[]) => {
...
@@ -212,10 +212,6 @@ const generateTableData = (propertyList: any[]) => {
if
(
index
!==
-
1
)
{
if
(
index
!==
-
1
)
{
continue
continue
}
}
/**
* TODO 嗯。。有一个问题回显数据时已删除的 sku 会被重新添加暂时没想到好办法,保存时先手动重新删除一下因为是一条空数据很好辨别 不手动删也没是提交表单时会检测删除空sku来兜底
*
*/
formData
.
value
.
skus
.
push
(
row
)
formData
.
value
.
skus
.
push
(
row
)
}
}
}
}
...
@@ -302,4 +298,6 @@ watch(
...
@@ -302,4 +298,6 @@ watch(
immediate
:
true
immediate
:
true
}
}
)
)
// 暴露出生成 sku 方法给添加属性成功时调用 fix: 为了在只有一个属性下 spu 回显 skus 属性和和商品属性个数一致的情况下 添加属性值时添加 sku
defineExpose
({
generateTableData
})
</
script
>
</
script
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment