莳松crm管理系统
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.
ss-crm-manage-web/src/views/MiniMall/Product/add.vue

277 lines
9.0 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">
1 year ago
<el-form-item label="产品名称" prop="productName">
<el-input v-model="form.productName" placeholder="请输入产品名称" />
1 year ago
</el-form-item>
</el-col>
<el-col :span="8" :offset="0">
1 year ago
<el-form-item label="分类" prop="productCategory">
<el-cascader
:options="opts.productCategory"
v-model="form.productCategory"
placeholder="请选择分类"
filterable
show-all-levels
1 year ago
style="width: 100%"
1 year ago
/>
1 year ago
</el-form-item>
</el-col>
<el-col :span="8" :offset="0">
1 year ago
<el-form-item label="品牌" prop="productBrand">
<el-select v-model="form.productBrand" placeholder="请选择品牌" filterable>
<el-option
v-for="item in opts.brand"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
1 year ago
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12" :offset="0">
1 year ago
<el-form-item label="产品简介" prop="productIntro">
1 year ago
<el-input
1 year ago
v-model="form.productIntro"
1 year ago
type="textarea"
:autosize="{ minRows: 4 }"
placeholder="请输入产品简介"
/>
</el-form-item>
</el-col>
<el-col :span="12" :offset="0">
1 year ago
<el-form-item label="主图" prop="mainImage">
<UploadImg v-model="form.mainImage" height="100px" width="100px" />
1 year ago
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24" :offset="0">
1 year ago
<el-form-item label="轮播图" prop="carouselImages">
<UploadImgs v-model="form.carouselImages" height="100px" width="100px" />
1 year ago
</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>
1 year ago
<el-col v-for="(item, index) in form.productSpecList" :key="index">
1 year ago
<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
1 year ago
v-for="col in form.productSpecList"
1 year ago
: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">
1 year ago
<Editor v-model:modelValue="form.detailInfo" />
1 year ago
</el-tab-pane>
</el-tabs>
1 year ago
<ProductAttributesAddForm ref="attributesAddFormRef" :propertyList="form.productSpecList" />
1 year ago
</template>
<script setup>
import ProductAttributesAddForm from './Comp/ProductAttributesAddForm.vue'
const route = useRoute()
const message = useMessage() // 消息弹窗
const tabName = ref('basic')
const form = ref({
1 year ago
productName: undefined,
productCategory: undefined,
productBrand: undefined,
productIntro: undefined,
mainImage: '',
carouselImages: [],
productSpecList: [],
1 year ago
skuList: [],
1 year ago
detailInfo: null
1 year ago
})
const rules = ref({})
const attributesAddFormRef = ref() // 添加商品属性表单
1 year ago
const opts = {
1 year ago
brand: [{ value: 1, label: '品牌1' }],
productCategory: [
{
id: 1,
label: '分类1',
children: [{ id: 2, label: '子分类1' }]
}
]
1 year ago
}
1 year ago
/** 删除属性*/
function handleCloseProperty(index) {
1 year ago
form.value.productSpecList?.splice(index, 1)
1 year ago
}
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)
1 year ago
form.value.productSpecList[index].values.push({ id, name: inputValue.value })
1 year ago
message.success('添加成功')
} catch {
message.error('添加失败,请重试')
}
}
attributeIndex.value = null
inputValue.value = ''
form.value.skuList = getTableList()
}
function getTableList() {
let list = []
1 year ago
form.value.productSpecList.map((item) => {
1 year ago
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() {
1 year ago
attributesAddFormRef.value.open()
1 year ago
}
function onSubmit() {
message.success('保存成功!')
}
onMounted(() => {
if (route.query?.id) {
form.value = {
1 year ago
productName: '商品名称哦~'
1 year ago
}
} else {
form.value = {
1 year ago
productName: undefined,
productCategory: undefined,
productBrand: undefined,
productIntro: undefined,
mainImage: 'https://ss-cloud.ahduima.com/1001/1796426117251600384.png',
carouselImages: ['https://ss-cloud.ahduima.com/1001/1796426117251600384.png'],
productSpecList: [],
1 year ago
skuList: [],
1 year ago
detailInfo: null
1 year ago
}
}
})
</script>
<style lang="scss" scoped></style>