You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
8.1 KiB
253 lines
8.1 KiB
![]()
1 year ago
|
<template>
|
||
|
<el-tabs v-model="tabName" type="border-card" tab-position="top">
|
||
|
<el-tab-pane label="商品信息" name="basic">
|
||
|
<el-form :model="form" ref="spuForm" :rules="rules" label-width="90px">
|
||
|
<el-row :gutter="20">
|
||
|
<el-col :span="8" :offset="0">
|
||
|
<el-form-item label="产品名称" prop="name">
|
||
|
<el-input v-model="form.name" placeholder="请输入产品名称" />
|
||
|
</el-form-item>
|
||
|
</el-col>
|
||
|
<el-col :span="8" :offset="0">
|
||
|
<el-form-item label="分类" prop="category">
|
||
|
<el-input v-model="form.category" placeholder="请输入分类" />
|
||
|
</el-form-item>
|
||
|
</el-col>
|
||
|
<el-col :span="8" :offset="0">
|
||
|
<el-form-item label="品牌" prop="brand">
|
||
|
<el-input v-model="form.brand" placeholder="请输入品牌" />
|
||
|
</el-form-item>
|
||
|
</el-col>
|
||
|
</el-row>
|
||
|
<el-row :gutter="20">
|
||
|
<el-col :span="12" :offset="0">
|
||
|
<el-form-item label="产品简介" prop="intro">
|
||
|
<el-input
|
||
|
v-model="form.intro"
|
||
|
type="textarea"
|
||
|
:autosize="{ minRows: 4 }"
|
||
|
placeholder="请输入产品简介"
|
||
|
/>
|
||
|
</el-form-item>
|
||
|
</el-col>
|
||
|
<el-col :span="12" :offset="0">
|
||
|
<el-form-item label="主图" prop="picUrl">
|
||
|
<UploadImg v-model="form.picUrl" height="100px" width="100px" />
|
||
|
</el-form-item>
|
||
|
</el-col>
|
||
|
</el-row>
|
||
|
<el-row :gutter="20">
|
||
|
<el-col :span="24" :offset="0">
|
||
|
<el-form-item label="轮播图" prop="sliderPicUrls">
|
||
|
<UploadImgs v-model:modelValue="form.sliderPicUrls" height="100px" width="100px" />
|
||
|
</el-form-item>
|
||
|
</el-col>
|
||
|
</el-row>
|
||
|
<el-row :gutter="20">
|
||
|
<el-col :span="24" :offset="0">
|
||
|
<el-form-item label="商品规格">
|
||
|
<el-button @click="handleAddSpec">添加规格</el-button>
|
||
|
<el-col v-for="(item, index) in form.specsList" :key="index">
|
||
|
<div>
|
||
|
<el-text class="mx-1">属性名:</el-text>
|
||
|
<el-tag class="mx-1" closable 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"
|
||
|
class="mx-1"
|
||
|
closable
|
||
|
@close="handleCloseValue(index, valueIndex)"
|
||
|
>
|
||
|
{{ value.name }}
|
||
|
</el-tag>
|
||
|
<el-input
|
||
|
v-show="inputVisible(index)"
|
||
|
:id="`input${index}`"
|
||
|
:ref="setInputRef"
|
||
|
v-model="inputValue"
|
||
|
class="!w-20"
|
||
|
size="small"
|
||
|
@blur="handleInputConfirm(index, item.id)"
|
||
|
@keyup.enter="handleInputConfirm(index, item.id)"
|
||
|
/>
|
||
|
<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>
|
||
|
</el-form-item>
|
||
|
<el-form-item>
|
||
|
<el-table :data="form.skuList">
|
||
|
<el-table-column type="index" width="50" />
|
||
|
<el-table-column prop="specsName" label="规格名称">
|
||
|
<template #default="{ row }">
|
||
|
<el-input v-model="row.specsName" placeholder="请输入" />
|
||
|
</template>
|
||
|
</el-table-column>
|
||
|
<el-table-column
|
||
|
v-for="col in form.specsList"
|
||
|
:prop="col.id"
|
||
|
:key="col.id"
|
||
|
:label="col.name"
|
||
|
/>
|
||
|
<el-table-column prop="price" label="销售价">
|
||
|
<template #default="{ row }">
|
||
|
<el-input-number v-model="row.price" :min="0.01" :step="1" />
|
||
|
</template>
|
||
|
</el-table-column>
|
||
|
<el-table-column prop="intro" label="简介">
|
||
|
<template #default="{ row }">
|
||
|
<el-input v-model="row.intro" placeholder="请输入简介" />
|
||
|
</template>
|
||
|
</el-table-column>
|
||
|
</el-table>
|
||
|
</el-form-item>
|
||
|
</el-col>
|
||
|
</el-row>
|
||
|
</el-form>
|
||
|
<div class="mt-20px flex justify-center">
|
||
|
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||
|
<el-button plain>重置</el-button>
|
||
|
</div>
|
||
|
</el-tab-pane>
|
||
|
<el-tab-pane label="详细信息" name="detail">
|
||
|
<Editor v-model:modelValue="form.description" />
|
||
|
</el-tab-pane>
|
||
|
</el-tabs>
|
||
|
<ProductAttributesAddForm ref="attributesAddFormRef" :propertyList="form.specsList" />
|
||
|
</template>
|
||
|
|
||
|
<script setup>
|
||
|
import ProductAttributesAddForm from './Comp/ProductAttributesAddForm.vue'
|
||
|
const route = useRoute()
|
||
|
const message = useMessage() // 消息弹窗
|
||
|
|
||
|
const tabName = ref('basic')
|
||
|
const form = ref({
|
||
|
name: '',
|
||
|
category: '',
|
||
|
brand: '',
|
||
|
intro: '',
|
||
|
picUrl: '',
|
||
|
sliderPicUrls: [],
|
||
|
specsList: [],
|
||
|
skuList: [],
|
||
|
description: null
|
||
|
})
|
||
|
const rules = ref({})
|
||
|
const attributesAddFormRef = ref() // 添加商品属性表单
|
||
|
|
||
|
/** 删除属性*/
|
||
|
function handleCloseProperty(index) {
|
||
|
form.value.specsList?.splice(index, 1)
|
||
|
}
|
||
|
|
||
|
const attributeIndex = ref(null)
|
||
|
// 输入框显隐控制
|
||
|
const inputVisible = computed(() => (index) => {
|
||
|
if (attributeIndex.value === null) return false
|
||
|
if (attributeIndex.value === index) return true
|
||
|
})
|
||
|
|
||
|
const inputValue = ref('') // 输入框值
|
||
|
/** 输入框失去焦点或点击回车时触发 */
|
||
|
async function handleInputConfirm(index, propertyId) {
|
||
|
if (inputValue.value) {
|
||
|
// 保存属性值
|
||
|
try {
|
||
|
// const id = await PropertyApi.createPropertyValue({ propertyId, name: inputValue.value })
|
||
|
const id = propertyId || parseInt(Math.random() * 1000000)
|
||
|
form.value.specsList[index].values.push({ id, name: inputValue.value })
|
||
|
message.success('添加成功')
|
||
|
} catch {
|
||
|
message.error('添加失败,请重试')
|
||
|
}
|
||
|
}
|
||
|
attributeIndex.value = null
|
||
|
inputValue.value = ''
|
||
|
form.value.skuList = getTableList()
|
||
|
}
|
||
|
|
||
|
function getTableList() {
|
||
|
let list = []
|
||
|
form.value.specsList.map((item) => {
|
||
|
if (!list.length) {
|
||
|
item.values.map((it) => {
|
||
|
const obj = {}
|
||
|
obj[it.id] = it.name
|
||
|
list.push(obj)
|
||
|
})
|
||
|
} else {
|
||
|
item.values.map((it, index) => {
|
||
|
if (index < list.length) {
|
||
|
list[index][it.id] = it.name
|
||
|
} else {
|
||
|
const obj = {}
|
||
|
obj[it.id] = it.name
|
||
|
list.push(obj)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
return list
|
||
|
}
|
||
|
|
||
|
const inputRef = ref([]) //标签输入框Ref
|
||
|
/** 显示输入框并获取焦点 */
|
||
|
const showInput = async (index) => {
|
||
|
attributeIndex.value = index
|
||
|
inputRef.value[index].focus()
|
||
|
}
|
||
|
|
||
|
/** 解决 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)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function handleAddSpec() {
|
||
|
const id = parseInt(Math.random() * 1000)
|
||
|
form.value.specsList.push({ name: `测试规格${id}`, id, values: [] })
|
||
|
}
|
||
|
|
||
|
function onSubmit() {
|
||
|
message.success('保存成功!')
|
||
|
}
|
||
|
|
||
|
onMounted(() => {
|
||
|
if (route.query?.id) {
|
||
|
form.value = {
|
||
|
name: '商品名称哦~'
|
||
|
}
|
||
|
} else {
|
||
|
form.value = {
|
||
|
name: '',
|
||
|
category: '',
|
||
|
brand: '',
|
||
|
intro: '',
|
||
|
picUrl: '',
|
||
|
sliderPicUrls: [],
|
||
|
specsList: [],
|
||
|
skuList: [],
|
||
|
description: null
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped></style>
|