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

View File

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

View File

@ -18,16 +18,28 @@
> >
{{ value.name }} {{ value.name }}
</el-tag> </el-tag>
<el-input <el-select
v-show="inputVisible(index)"
:id="`input${index}`" :id="`input${index}`"
:ref="setInputRef" :ref="setInputRef"
v-show="inputVisible(index)"
v-model="inputValue" v-model="inputValue"
class="!w-20" filterable
allow-create
default-first-option
:reserve-keyword="false"
size="small" size="small"
class="!w-30"
@blur="handleInputConfirm(index, item.id)" @blur="handleInputConfirm(index, item.id)"
@keyup.enter="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 <el-button
v-show="!inputVisible(index)" v-show="!inputVisible(index)"
class="button-new-tag ml-1" class="button-new-tag ml-1"
@ -42,10 +54,10 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ElInput } from 'element-plus'
import * as PropertyApi from '@/api/mall/product/property' import * as PropertyApi from '@/api/mall/product/property'
import { PropertyAndValues } from '@/views/mall/product/spu/components' import { PropertyAndValues } from '@/views/mall/product/spu/components'
import { propTypes } from '@/utils/propTypes' import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
defineOptions({ name: 'ProductAttributes' }) defineOptions({ name: 'ProductAttributes' })
@ -109,6 +121,15 @@ const showInput = async (index) => {
const emit = defineEmits(['success']) // success const emit = defineEmits(['success']) // success
const handleInputConfirm = async (index: number, propertyId: number) => { const handleInputConfirm = async (index: number, propertyId: number) => {
if (inputValue.value) { 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 { try {
const id = await PropertyApi.createPropertyValue({ propertyId, name: inputValue.value }) const id = await PropertyApi.createPropertyValue({ propertyId, name: inputValue.value })

View File

@ -10,7 +10,22 @@
@keydown.enter.prevent="submitForm" @keydown.enter.prevent="submitForm"
> >
<el-form-item label="属性名称" prop="name"> <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-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -24,6 +39,7 @@ import * as PropertyApi from '@/api/mall/product/property'
defineOptions({ name: 'ProductPropertyForm' }) defineOptions({ name: 'ProductPropertyForm' })
const emit = defineEmits(['success']) // success
const { t } = useI18n() // const { t } = useI18n() //
const message = useMessage() // const message = useMessage() //
@ -37,6 +53,7 @@ const formRules = reactive({
}) })
const formRef = ref() // Ref const formRef = ref() // Ref
const attributeList = ref([]) // const attributeList = ref([]) //
const attrOption = ref([]) //
const props = defineProps({ const props = defineProps({
propertyList: { propertyList: {
type: Array, type: Array,
@ -59,6 +76,7 @@ watch(
/** 打开弹窗 */ /** 打开弹窗 */
const open = async () => { const open = async () => {
dialogVisible.value = true dialogVisible.value = true
getAttrOption()
resetForm() resetForm()
} }
defineExpose({ open }) // open defineExpose({ open }) // open
@ -80,6 +98,15 @@ const submitForm = async () => {
...formData.value, ...formData.value,
values: [] 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')) message.success(t('common.createSuccess'))
dialogVisible.value = false dialogVisible.value = false
} finally { } finally {
@ -94,4 +121,16 @@ const resetForm = () => {
} }
formRef.value?.resetFields() 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> </script>

View File

@ -1,6 +1,13 @@
<!-- 商品发布 - 库存价格 --> <!-- 商品发布 - 库存价格 -->
<template> <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-form-item label="分销类型" props="subCommissionType">
<el-radio-group <el-radio-group
v-model="formData.subCommissionType" v-model="formData.subCommissionType"
@ -51,9 +58,14 @@
</el-form> </el-form>
<!-- 商品属性添加 Form 表单 --> <!-- 商品属性添加 Form 表单 -->
<ProductPropertyAddForm ref="attributesAddFormRef" :propertyList="propertyList" /> <ProductPropertyAddForm
ref="attributesAddFormRef"
:propertyList="propertyList"
@success="getPropertyValueList"
/>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import * as PropertyApi from '@/api/mall/product/property'
import { PropType } from 'vue' import { PropType } from 'vue'
import { copyValueToTarget } from '@/utils' import { copyValueToTarget } from '@/utils'
import { propTypes } from '@/utils/propTypes' import { propTypes } from '@/utils/propTypes'
@ -94,7 +106,7 @@ const ruleConfig: RuleConfig[] = [
] ]
const message = useMessage() // const message = useMessage() //
const formLoading = ref(false)
const props = defineProps({ const props = defineProps({
propFormData: { propFormData: {
type: Object as PropType<Spu>, type: Object as PropType<Spu>,
@ -184,4 +196,16 @@ const onChangeSpec = () => {
const generateSkus = (propertyList: any[]) => { const generateSkus = (propertyList: any[]) => {
skuListRef.value.generateTableData(propertyList) 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> </script>