review + mall:商品管理

This commit is contained in:
YunaiV 2023-05-24 20:27:45 +08:00
parent c296c9e53d
commit 0fba3fd503
8 changed files with 63 additions and 59 deletions

View File

@ -102,7 +102,8 @@ const include = [
'element-plus/es/components/timeline-item/style/css',
'element-plus/es/components/collapse/style/css',
'element-plus/es/components/collapse-item/style/css',
'element-plus/es/components/button-group/style/css'
'element-plus/es/components/button-group/style/css',
'element-plus/es/components/text/style/css'
]
const exclude = ['@iconify/json']

View File

@ -7,6 +7,7 @@ export interface Property {
valueName?: string // 属性值名称
}
// TODO puhui999是不是直接叫 Sku 更简洁一点哈。type 待后面,总感觉有个类型?
export interface SkuType {
id?: number // 商品 SKU 编号
spuId?: number // SPU 编号
@ -24,6 +25,7 @@ export interface SkuType {
salesCount?: number // 商品销量
}
// TODO puhui999是不是直接叫 Spu 更简洁一点哈。type 待后面,总感觉有个类型?
export interface SpuType {
id?: number
name?: string // 商品名称

View File

@ -174,6 +174,7 @@ export const copyValueToTarget = (target, source) => {
Object.assign(target, newObj)
}
// TODO @puhui999返回要带上 .00 哈.例如说 1.00
/**
*
* @param num

View File

@ -146,7 +146,6 @@ const submitForm = async () => {
const newSliderPicUrls = []
deepCopyFormData.sliderPicUrls.forEach((item) => {
//
// TODO @puhui999 object fix
typeof item === 'object' ? newSliderPicUrls.push(item.url) : newSliderPicUrls.push(item)
})
deepCopyFormData.sliderPicUrls = newSliderPicUrls

View File

@ -96,7 +96,6 @@
<!-- 多规格添加-->
<el-col :span="24">
<el-form-item v-if="formData.specType" label="商品属性">
<!-- TODO @puhui999参考 https://admin.java.crmeb.net/store/list/creatProduct fix-->
<el-button class="mr-15px mb-10px" @click="attributesAddFormRef.open">添加规格</el-button>
<ProductAttributes :propertyList="propertyList" @success="generateSkus" />
</el-form-item>
@ -137,9 +136,8 @@ const props = defineProps({
},
activeName: propTypes.string.def('')
})
const attributesAddFormRef = ref() // TODO @puhui999 fix
const productSpuBasicInfoRef = ref() // Ref TODO @puhui999 fix
// TODO @puhui999attributeList propertyList fix
const attributesAddFormRef = ref() //
const productSpuBasicInfoRef = ref() // Ref
const propertyList = ref([]) //
const skuListRef = ref() // Ref
/** 调用 SkuList generateTableData 方法*/
@ -180,17 +178,17 @@ const rules = reactive({
watch(
() => props.propFormData,
(data) => {
if (!data) return
// fix使 copyValueToTarget 使 formData.value = data
if (!data) {
return
}
copyValueToTarget(formData, data)
// fix: url
formData.sliderPicUrls = data['sliderPicUrls'].map((item) => ({
url: item
}))
// TODO @puhui999if return
//
if (formData.specType) {
// TODO @puhui999 propertyName id + uniapp
// fix: skus propertyList
// skus propertyList
const properties = []
formData.skus.forEach((sku) => {
sku.properties.forEach(({ propertyId, propertyName, valueId, valueName }) => {
@ -209,7 +207,6 @@ watch(
}
},
{
// fix: ,
immediate: true
}
)

View File

@ -1,7 +1,6 @@
<template>
<el-form ref="otherSettingsFormRef" :model="formData" :rules="rules" label-width="120px">
<el-row>
<!-- TODO @puhui999横着三个哈 fix-->
<el-col :span="24">
<el-row :gutter="20">
<el-col :span="8">
@ -35,7 +34,7 @@
</el-form-item>
</el-col>
<el-col :span="24">
<!-- TODO tag展示暂时不考虑排序 -->
<!-- TODO tag展示暂时不考虑排序 -->
<el-form-item label="活动优先级">
<el-tag>默认</el-tag>
<el-tag class="ml-2" type="success">秒杀</el-tag>
@ -86,7 +85,6 @@ const rules = reactive({
giveIntegral: [required],
virtualSalesCount: [required]
})
// TODO @puhui999 recommendOptions fix
const recommendOptions = [
{ name: '是否热卖', value: 'recommendHot' },
{ name: '是否优惠', value: 'recommendBenefit' },
@ -98,7 +96,6 @@ const checkboxGroup = ref<string[]>([]) // 选中的推荐选项
/** 选择商品后赋值 */
const onChangeGroup = () => {
// TODO @puhui999 recommendfix
recommendOptions.forEach(({ value }) => {
formData.value[value] = checkboxGroup.value.includes(value)
})
@ -110,21 +107,21 @@ const onChangeGroup = () => {
watch(
() => props.propFormData,
(data) => {
if (!data) return
// fix使 copyValueToTarget 使 formData.value = data
if (!data) {
return
}
copyValueToTarget(formData.value, data)
recommendOptions.forEach(({ value }) => {
// TODO fix:
if (formData.value[value] && !checkboxGroup.value.includes(value)) {
checkboxGroup.value.push(value)
}
})
},
{
// fix: ,
immediate: true
}
)
/**
* 表单校验
*/

View File

@ -12,7 +12,7 @@
</template>
</el-table-column>
<template v-if="formData.specType && !isBatch">
<!-- 根据商品属性动态添加 -->
<!-- 根据商品属性动态添加 -->
<el-table-column
v-for="(item, index) in tableHeaders"
:key="index"
@ -21,17 +21,16 @@
min-width="120"
>
<template #default="{ row }">
<!-- TODO puhui999展示成蓝色有点区分度哈 -->
{{ row.properties[index]?.valueName }}
</template>
</el-table-column>
</template>
<!-- TODO @puhui999 controls-position=" " 可以去掉哈不然太长了手动输入更方便 fix -->
<el-table-column align="center" label="商品条码" min-width="168">
<template #default="{ row }">
<el-input v-model="row.barCode" class="w-100%" />
</template>
</el-table-column>
<!-- TODO @puhui999用户输入的时候是按照元分主要是我们自己用fix -->
<el-table-column align="center" label="销售价(元)" min-width="168">
<template #default="{ row }">
<el-input-number v-model="row.price" :min="0" :precision="2" :step="0.1" class="w-100%" />
@ -141,6 +140,7 @@ const skuList = ref<SkuType[]>([
subCommissionSecondPrice: 0 //
}
]) //
// TODO @puhui999 0.01
/** 批量添加 */
const batchAdd = () => {
@ -148,6 +148,7 @@ const batchAdd = () => {
copyValueToTarget(item, skuList.value[0])
})
}
/** 删除 sku */
const deleteSku = (row) => {
const index = formData.value.skus.findIndex(
@ -159,7 +160,7 @@ const deleteSku = (row) => {
const tableHeaders = ref<{ prop: string; label: string }[]>([]) //
/**
* 将传进来的值赋值给skuList
* 将传进来的值赋值给 skuList
*/
watch(
() => props.propFormData,
@ -173,11 +174,10 @@ watch(
}
)
// TODO @ chatgpt fix:
/** 生成表数据 */
const generateTableData = (propertyList: any[]) => {
// fix: 使mapfor
const propertiesItemList = propertyList.map((item) =>
//
const propertyValues = propertyList.map((item) =>
item.values.map((v) => ({
propertyId: item.id,
propertyName: item.name,
@ -185,15 +185,16 @@ const generateTableData = (propertyList: any[]) => {
valueName: v.name
}))
)
const buildList = build(propertiesItemList)
// TODO @puhui buildSkuListitem sku
const buildList = build(propertyValues)
// sku skus
if (!validateData(propertyList)) {
// sku
// sku
formData.value!.skus = []
}
for (const item of buildList) {
const row = {
properties: Array.isArray(item) ? item : [item], // property
properties: Array.isArray(item) ? item : [item], // property
price: 0,
marketPrice: 0,
costPrice: 0,
@ -205,16 +206,17 @@ const generateTableData = (propertyList: any[]) => {
subCommissionFirstPrice: 0,
subCommissionSecondPrice: 0
}
// sku
const index = formData.value!.skus.findIndex(
(sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
)
// sku
if (index !== -1) {
continue
}
formData.value.skus.push(row)
}
}
/**
* 生成 skus 前置校验
*/
@ -232,6 +234,7 @@ const validateData = (propertyList: any[]) => {
const propertyIds = propertyList.map((item) => item.id)
return skuPropertyIds.length === propertyIds.length
}
/** 构建所有排列组合 */
const build = (propertyValuesList: Property[][]) => {
if (propertyValuesList.length === 0) {
@ -255,13 +258,15 @@ const build = (propertyValuesList: Property[][]) => {
}
}
/** 监听属性列表生成相关参数和表头 */
/** 监听属性列表生成相关参数和表头 */
watch(
() => props.propertyList,
(propertyList) => {
//
if (!formData.value.specType) return
// 使
if (!formData.value.specType) {
return
}
// 使
if (props.isBatch) {
skuList.value = [
{
@ -278,8 +283,11 @@ watch(
}
]
}
//
if (JSON.stringify(propertyList) === '[]') return
if (JSON.stringify(propertyList) === '[]') {
return
}
//
tableHeaders.value = []
//
@ -287,10 +295,16 @@ watch(
// nameindex
tableHeaders.value.push({ prop: `name${index}`, label: item.name })
})
// sku
if (validateData(propertyList)) return
if (validateData(propertyList)) {
return
}
//
if (propertyList.some((item) => item.values.length === 0)) return
if (propertyList.some((item) => item.values.length === 0)) {
return
}
// table sku
generateTableData(propertyList)
},
{
@ -298,6 +312,6 @@ watch(
immediate: true
}
)
// sku fix: spu skus sku
// sku
defineExpose({ generateTableData })
</script>

View File

@ -8,7 +8,7 @@
class="-mb-15px"
label-width="68px"
>
<!-- TODO @puhui999https://admin.java.crmeb.net/store/index使 + fix-->
<!-- TODO @puhui999品牌应该是数据下拉哈 -->
<el-form-item label="品牌名称" prop="name">
<el-input
v-model="queryParams.name"
@ -19,6 +19,7 @@
/>
</el-form-item>
<!-- TODO 分类只能选择二级分类目前还没做还是先以联调通顺为主 -->
<!-- TODO puhui999我们要不改成支持选择一级如果选择一级后端要递归查询下子分类然后去 in -->
<el-form-item label="商品分类" prop="categoryId">
<el-tree-select
v-model="queryParams.categoryId"
@ -70,7 +71,12 @@
/>
</el-tabs>
<el-table v-loading="loading" :data="list">
<!-- TODO 折叠数据按需增加暂定以下三个 -->
<!-- TODO puhui这几个属性哈一行三个
商品分类服装鞋包/箱包
商品市场价格100.00
成本价0.00
收藏5
虚拟销量999 -->
<el-table-column type="expand" width="30">
<template #default="{ row }">
<el-form class="demo-table-expand" inline label-position="left">
@ -86,19 +92,13 @@
</el-form>
</template>
</el-table-column>
<!-- TODO puhui999: ID 编号的展示 fix-->
<el-table-column key="id" align="center" label="商品编号" prop="id" />
<el-table-column label="商品图" min-width="80">
<template #default="{ row }">
<el-image
:src="row.picUrl"
style="width: 30px; height: 30px"
@click="imagePreview(row.picUrl)"
/>
<el-image :src="row.picUrl" @click="imagePreview(row.picUrl)" class="w-30px h-30px" />
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" label="商品名称" min-width="300" prop="name" />
<!-- TODO 价格 / 100.0 -->
<el-table-column align="center" label="商品售价" min-width="90" prop="price">
<template #default="{ row }">
{{ formatToFraction(row.price) }}
@ -116,7 +116,6 @@
/>
<el-table-column align="center" label="状态" min-width="80">
<template #default="{ row }">
<!-- fix: 修复打开回收站时商品误触改变商品状态的事件因为el-switch只用0和1没有-1所以当商品状态为-1时状态使用el-tag显示 -->
<template v-if="row.status >= 0">
<el-switch
v-model="row.status"
@ -238,7 +237,6 @@ const tabsData = ref([
/** 获得每个 Tab 的数量 */
const getTabsCount = async () => {
// TODO @puhui999 try catch fix
const res = await ProductSpuApi.getTabsCount()
for (let objName in res) {
tabsData.value[Number(objName)].count = res[objName]
@ -251,7 +249,6 @@ const queryParams = ref({
}) //
const queryFormRef = ref() // Ref
// TODO @puhui999 handleTabClickfix
const handleTabClick = (tab: TabsPaneContext) => {
queryParams.value.tabType = tab.paneName
getList()
@ -269,7 +266,6 @@ const getList = async () => {
}
}
// TODO @puhui999 changeStatus addToTrash fix
/**
* 更改 SPU 状态
*
@ -277,7 +273,6 @@ const getList = async () => {
* @param status 更改前的值
*/
const changeStatus = async (row, status?: number) => {
// fix: changeStatus
const deepCopyValue = cloneDeep(unref(row))
if (typeof status !== 'undefined') deepCopyValue.status = status
try {
@ -293,7 +288,6 @@ const changeStatus = async (row, status?: number) => {
text = `加入${ProductSpuStatusEnum.RECYCLE.name}`
break
}
// fix:
await message.confirm(
deepCopyValue.status === -1
? `确认要将[${row.name}]${text}吗?`
@ -331,12 +325,8 @@ const handleDelete = async (id: number) => {
} catch {}
}
/**
* 商品图预览
* @param imgUrl
*/
/** 商品图预览 */
const imagePreview = (imgUrl: string) => {
// fix: https://kailong110120130.gitee.io/vue-element-plus-admin-doc/components/image-viewer.html
createImageViewer({
urlList: [imgUrl]
})
@ -367,19 +357,22 @@ const openForm = (id?: number) => {
//
push('/product/productSpuAdd')
}
/**
* 查看商品详情
*/
const openDetail = () => {
message.alert('查看详情未完善!!!')
}
// TODO @puhui999fix:
//
watch(
() => currentRoute.value,
() => {
getList()
}
)
const categoryList = ref() //
/** 初始化 **/
onMounted(async () => {