From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/views/mall/product/spu/form/ProductAttributes.vue | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 162 insertions(+), 0 deletions(-)
diff --git a/src/views/mall/product/spu/form/ProductAttributes.vue b/src/views/mall/product/spu/form/ProductAttributes.vue
new file mode 100644
index 0000000..1bb24ff
--- /dev/null
+++ b/src/views/mall/product/spu/form/ProductAttributes.vue
@@ -0,0 +1,162 @@
+<!-- 鍟嗗搧鍙戝竷 - 搴撳瓨浠锋牸 - 灞炴�у垪琛� -->
+<template>
+ <el-col v-for="(item, index) in attributeList" :key="index">
+ <div>
+ <el-text class="mx-1">灞炴�у悕锛�</el-text>
+ <el-tag :closable="!isDetail" class="mx-1" type="success" @close="handleCloseProperty(index)">
+ {{ item.name }}
+ </el-tag>
+ </div>
+ <div>
+ <el-text class="mx-1">灞炴�у�硷細</el-text>
+ <el-tag
+ v-for="(value, valueIndex) in item.values"
+ :key="value.id"
+ :closable="!isDetail"
+ class="mx-1"
+ @close="handleCloseValue(index, valueIndex)"
+ >
+ {{ value.name }}
+ </el-tag>
+ <el-select
+ v-show="inputVisible(index)"
+ :id="`input${index}`"
+ :ref="setInputRef"
+ v-model="inputValue"
+ :reserve-keyword="false"
+ allow-create
+ class="!w-30"
+ default-first-option
+ filterable
+ size="small"
+ @blur="handleInputConfirm(index, item.id)"
+ @change="handleInputConfirm(index, item.id)"
+ @keyup.enter="handleInputConfirm(index, item.id)"
+ >
+ <el-option
+ v-for="item2 in attributeOptions"
+ :key="item2.id"
+ :label="item2.name"
+ :value="item2.name"
+ />
+ </el-select>
+ <el-button
+ v-show="!inputVisible(index)"
+ class="button-new-tag ml-1"
+ size="small"
+ @click="showInput(index)"
+ >
+ + 娣诲姞
+ </el-button>
+ </div>
+ <el-divider class="my-10px" />
+ </el-col>
+</template>
+
+<script lang="ts" setup>
+import * as PropertyApi from '@/api/mall/product/property'
+import { PropertyAndValues } from '@/views/mall/product/spu/components'
+import { propTypes } from '@/utils/propTypes'
+
+defineOptions({ name: 'ProductAttributes' })
+
+const { t } = useI18n() // 鍥介檯鍖�
+const message = useMessage() // 娑堟伅寮圭獥
+const inputValue = ref('') // 杈撳叆妗嗗��
+const attributeIndex = ref<number | null>(null) // 鑾峰彇鐒︾偣鏃惰褰曞綋鍓嶅睘鎬ч」鐨刬ndex
+// 杈撳叆妗嗘樉闅愭帶鍒�
+const inputVisible = computed(() => (index: number) => {
+ if (attributeIndex.value === null) return false
+ if (attributeIndex.value === index) return true
+})
+const inputRef = ref<any[]>([]) //鏍囩杈撳叆妗哛ef
+/** 瑙e喅 ref 鍦� v-for 涓殑鑾峰彇闂*/
+const setInputRef = (el: any) => {
+ if (el === null || typeof el === 'undefined') return
+ // 濡傛灉涓嶅瓨鍦� id 鐩稿悓鐨勫厓绱犳墠娣诲姞
+ if (!inputRef.value.some((item) => item.inputRef?.attributes.id === el.inputRef?.attributes.id)) {
+ inputRef.value.push(el)
+ }
+}
+const attributeList = ref<PropertyAndValues[]>([]) // 鍟嗗搧灞炴�у垪琛�
+const attributeOptions = ref([] as PropertyApi.PropertyValueVO[]) // 鍟嗗搧灞炴�у悕绉颁笅鎷夋
+const props = defineProps({
+ propertyList: {
+ type: Array,
+ default: () => {}
+ },
+ isDetail: propTypes.bool.def(false) // 鏄惁浣滀负璇︽儏缁勪欢
+})
+
+watch(
+ () => props.propertyList,
+ (data) => {
+ if (!data) return
+ attributeList.value = data as any
+ },
+ {
+ deep: true,
+ immediate: true
+ }
+)
+
+/** 鍒犻櫎灞炴�у��*/
+const handleCloseValue = (index: number, valueIndex: number) => {
+ attributeList.value[index].values?.splice(valueIndex, 1)
+}
+
+/** 鍒犻櫎灞炴��*/
+const handleCloseProperty = (index: number) => {
+ attributeList.value?.splice(index, 1)
+ emit('success', attributeList.value)
+}
+
+/** 鏄剧ず杈撳叆妗嗗苟鑾峰彇鐒︾偣 */
+const showInput = async (index: number) => {
+ attributeIndex.value = index
+ inputRef.value[index].focus()
+ // 鑾峰彇灞炴�т笅鎷夐�夐」
+ await getAttributeOptions(attributeList.value[index].id)
+}
+
+/** 杈撳叆妗嗗け鍘荤劍鐐规垨鐐瑰嚮鍥炶溅鏃惰Е鍙� */
+const emit = defineEmits(['success']) // 瀹氫箟 success 浜嬩欢锛岀敤浜庢搷浣滄垚鍔熷悗鐨勫洖璋�
+const handleInputConfirm = async (index: number, propertyId: number) => {
+ if (inputValue.value) {
+ // 1. 閲嶅娣诲姞鏍¢獙
+ if (attributeList.value[index].values.find((item) => item.name === inputValue.value)) {
+ message.warning('宸插瓨鍦ㄧ浉鍚屽睘鎬у�硷紝璇烽噸璇�')
+ attributeIndex.value = null
+ inputValue.value = ''
+ return
+ }
+
+ // 2.1 鎯呭喌涓�锛氬睘鎬у�煎凡瀛樺湪锛屽垯鐩存帴浣跨敤骞剁粨鏉�
+ const existValue = attributeOptions.value.find((item) => item.name === inputValue.value)
+ if (existValue) {
+ attributeIndex.value = null
+ inputValue.value = ''
+ attributeList.value[index].values.push({ id: existValue.id, name: existValue.name })
+ emit('success', attributeList.value)
+ return
+ }
+
+ // 2.2 鎯呭喌浜岋細鏂板睘鎬у�硷紝鍒欒繘琛屼繚瀛�
+ try {
+ const id = await PropertyApi.createPropertyValue({ propertyId, name: inputValue.value })
+ attributeList.value[index].values.push({ id, name: inputValue.value })
+ message.success(t('common.createSuccess'))
+ emit('success', attributeList.value)
+ } catch {
+ message.error('娣诲姞澶辫触锛岃閲嶈瘯')
+ }
+ }
+ attributeIndex.value = null
+ inputValue.value = ''
+}
+
+/** 鑾峰彇鍟嗗搧灞炴�т笅鎷夐�夐」 */
+const getAttributeOptions = async (propertyId: number) => {
+ attributeOptions.value = await PropertyApi.getPropertyValueSimpleList(propertyId)
+}
+</script>
--
Gitblit v1.8.0