Merge pull request #71 from GoldenZqqq/GoldenZqqq/issue47

【功能优化】添加商品属性时允许选择已有的属性值
pull/495/head
芋道源码 2024-08-13 22:57:32 +08:00 committed by GitHub
commit e7c9ca0c5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 97 additions and 12 deletions

View File

@ -24,7 +24,7 @@
>
<template #default="{ row }">
<span style="font-weight: bold; color: #40aaff">
{{ row.properties[index]?.valueName }}
{{ row.properties?.[index]?.valueName }}
</span>
</template>
</el-table-column>
@ -168,7 +168,7 @@
>
<template #default="{ row }">
<span style="font-weight: bold; color: #40aaff">
{{ row.properties[index]?.valueName }}
{{ row.properties?.[index]?.valueName }}
</span>
</template>
</el-table-column>
@ -248,7 +248,7 @@
>
<template #default="{ row }">
<span style="font-weight: bold; color: #40aaff">
{{ row.properties[index]?.valueName }}
{{ row.properties?.[index]?.valueName }}
</span>
</template>
</el-table-column>

View File

@ -5,6 +5,7 @@ interface PropertyAndValues {
id: number
name: string
values?: PropertyAndValues[]
propertyOpts?: PropertyAndValues[]
}
interface RuleConfig {

View File

@ -18,16 +18,28 @@
>
{{ value.name }}
</el-tag>
<el-input
v-show="inputVisible(index)"
<el-select
:id="`input${index}`"
:ref="setInputRef"
v-show="inputVisible(index)"
v-model="inputValue"
class="!w-20"
filterable
allow-create
default-first-option
:reserve-keyword="false"
size="small"
class="!w-30"
@blur="handleInputConfirm(index, item.id)"
@keyup.enter="handleInputConfirm(index, item.id)"
@change="handleInputConfirm(index, item.id)"
>
<el-option
v-for="item2 in item.propertyOpts"
:key="item2.id"
:label="item2.name"
:value="item2.id"
/>
</el-select>
<el-button
v-show="!inputVisible(index)"
class="button-new-tag ml-1"
@ -42,10 +54,10 @@
</template>
<script lang="ts" setup>
import { ElInput } from 'element-plus'
import * as PropertyApi from '@/api/mall/product/property'
import { PropertyAndValues } from '@/views/mall/product/spu/components'
import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
defineOptions({ name: 'ProductAttributes' })
@ -109,6 +121,15 @@ const showInput = async (index) => {
const emit = defineEmits(['success']) // success
const handleInputConfirm = async (index: number, propertyId: number) => {
if (inputValue.value) {
//
if (isNumber(inputValue.value)) {
if (attributeList.value[index].values?.some((item) => item.id === inputValue.value)) {
message.warning('已存在相同属性值,请重试')
attributeIndex.value = null
inputValue.value = ''
return
}
}
//
try {
const id = await PropertyApi.createPropertyValue({ propertyId, name: inputValue.value })

View File

@ -10,7 +10,22 @@
@keydown.enter.prevent="submitForm"
>
<el-form-item label="属性名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" />
<el-select
v-model="formData.name"
filterable
allow-create
default-first-option
:reserve-keyword="false"
placeholder="请选择属性名称"
style="width: 240px"
>
<el-option
v-for="item in attrOption"
:key="item.id"
:label="item.name"
:value="item.name"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
@ -24,6 +39,7 @@ import * as PropertyApi from '@/api/mall/product/property'
defineOptions({ name: 'ProductPropertyForm' })
const emit = defineEmits(['success']) // success
const { t } = useI18n() //
const message = useMessage() //
@ -37,6 +53,7 @@ const formRules = reactive({
})
const formRef = ref() // Ref
const attributeList = ref([]) //
const attrOption = ref([]) //
const props = defineProps({
propertyList: {
type: Array,
@ -59,6 +76,7 @@ watch(
/** 打开弹窗 */
const open = async () => {
dialogVisible.value = true
getAttrOption()
resetForm()
}
defineExpose({ open }) // open
@ -80,6 +98,15 @@ const submitForm = async () => {
...formData.value,
values: []
})
// emit
for (const element of attrOption.value) {
if (element.name === formData.value.name) {
emit('success', propertyId, element.id)
message.success(t('common.createSuccess'))
dialogVisible.value = false
return
}
}
message.success(t('common.createSuccess'))
dialogVisible.value = false
} finally {
@ -94,4 +121,16 @@ const resetForm = () => {
}
formRef.value?.resetFields()
}
/** 获取商品属性下拉选项 */
const getAttrOption = async () => {
formLoading.value = true
try {
// TODO @
const data = await PropertyApi.getPropertyPage({ pageNo: 1, pageSize: 100 })
attrOption.value = data.list
} finally {
formLoading.value = false
}
}
</script>

View File

@ -1,6 +1,13 @@
<!-- 商品发布 - 库存价格 -->
<template>
<el-form ref="formRef" :disabled="isDetail" :model="formData" :rules="rules" label-width="120px">
<el-form
ref="formRef"
:disabled="isDetail"
:model="formData"
:rules="rules"
label-width="120px"
v-loading="formLoading"
>
<el-form-item label="分销类型" props="subCommissionType">
<el-radio-group
v-model="formData.subCommissionType"
@ -51,9 +58,14 @@
</el-form>
<!-- 商品属性添加 Form 表单 -->
<ProductPropertyAddForm ref="attributesAddFormRef" :propertyList="propertyList" />
<ProductPropertyAddForm
ref="attributesAddFormRef"
:propertyList="propertyList"
@success="getPropertyValueList"
/>
</template>
<script lang="ts" setup>
import * as PropertyApi from '@/api/mall/product/property'
import { PropType } from 'vue'
import { copyValueToTarget } from '@/utils'
import { propTypes } from '@/utils/propTypes'
@ -94,7 +106,7 @@ const ruleConfig: RuleConfig[] = [
]
const message = useMessage() //
const formLoading = ref(false)
const props = defineProps({
propFormData: {
type: Object as PropType<Spu>,
@ -184,4 +196,16 @@ const onChangeSpec = () => {
const generateSkus = (propertyList: any[]) => {
skuListRef.value.generateTableData(propertyList)
}
/* 获取属性值列表 */
const getPropertyValueList = async (id, propertyId) => {
formLoading.value = true
try {
// TODO @
const data = await PropertyApi.getPropertyValuePage({ pageNo: 1, pageSize: 100, propertyId })
propertyList.value.find((item) => item.id === id).propertyOpts = data.list
} finally {
formLoading.value = false
}
}
</script>