|
@@ -78,66 +78,178 @@
|
|
|
</Page>
|
|
|
<!-- 分页 -->
|
|
|
<!-- 添加或修改商品管理对话框 -->
|
|
|
- <el-dialog :title="title" :visible.sync="open" width="50%" append-to-body>
|
|
|
- <el-row :gutter="15">
|
|
|
- <el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
|
|
- <el-col :span="24">
|
|
|
- <el-form-item label="商品名称" prop="goodsName">
|
|
|
- <el-input v-model="form.goodsName" placeholder="请输入商品名称" />
|
|
|
+ <el-dialog :title="title" :visible.sync="open" width="70%" append-to-body>
|
|
|
+ <el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
|
|
+ <el-tabs v-model="activeTab">
|
|
|
+ <!-- 基本信息 tab -->
|
|
|
+ <el-tab-pane label="基本信息" name="basic">
|
|
|
+ <el-row :gutter="15">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="商品名称" prop="goodsName">
|
|
|
+ <el-input v-model="form.goodsName" placeholder="请输入商品名称" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="商品编码" prop="goodsCode">
|
|
|
+ <el-input v-model="form.goodsCode" placeholder="请输入商品编码" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-row :gutter="15">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="品牌" prop="brandId">
|
|
|
+ <el-select v-model="form.brandId" placeholder="请选择品牌" clearable>
|
|
|
+ <el-option v-for="brand in brandList" :key="brand.id" :label="brand.brandName" :value="brand.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="商品分类" prop="goodsCategoryId">
|
|
|
+ <el-select v-model="form.goodsCategoryId" placeholder="请选择商品分类" clearable>
|
|
|
+ <el-option v-for="category in categoryList" :key="category.id" :label="category.categoryName" :value="category.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <el-form-item label="商品图片" prop="goodsImg">
|
|
|
+ <image-upload v-model="form.goodsImg" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="品牌" prop="brandId">
|
|
|
- <el-select v-model="form.brandId" placeholder="请选择商品分类" clearable>
|
|
|
- <el-option v-for="brand in brandList" :key="brand.id" :label="brand.brandName" :value="brand.id" />
|
|
|
- </el-select>
|
|
|
+
|
|
|
+ <el-form-item label="商品图片集" prop="goodsImgs">
|
|
|
+ <image-upload v-model="form.goodsImgs" :limit="limit" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="商品分类" prop="goodsCategoryId">
|
|
|
- <el-select v-model="form.goodsCategoryId" placeholder="请选择商品分类" clearable>
|
|
|
- <el-option v-for="category in categoryList" :key="category.id" :label="category.categoryName" :value="category.id" />
|
|
|
- </el-select>
|
|
|
+
|
|
|
+ <el-form-item label="商品简介" prop="goodsSynopsis">
|
|
|
+ <editor v-model="form.goodsSynopsis" :min-height="192" />
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="商品编码" prop="goodsCode">
|
|
|
- <el-input v-model="form.goodsCode" placeholder="请输入商品编码" />
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <!-- 规格设置 tab -->
|
|
|
+ <el-tab-pane label="规格设置" name="sku">
|
|
|
+ <el-form-item label="规格类型">
|
|
|
+ <el-radio-group v-model="skuType" @change="handleSkuTypeChange">
|
|
|
+ <el-radio :label="0">单规格</el-radio>
|
|
|
+ <el-radio :label="1">多规格</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
</el-form-item>
|
|
|
- <template v-if="goodsType === '0'">
|
|
|
- <el-form-item label="促销标识" prop="isSell">
|
|
|
- <el-radio-group v-model="form.isSell" size="small">
|
|
|
- <el-radio-button v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code">{{ dict.label }}</el-radio-button>
|
|
|
- </el-radio-group>
|
|
|
+
|
|
|
+ <!-- 单规格设置 -->
|
|
|
+ <template v-if="skuType === 0">
|
|
|
+ <el-form-item label="销售价格" prop="singleSkuPrice">
|
|
|
+ <el-input-number v-model="form.singleSkuPrice" :precision="2" :step="0.1" :min="0" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="库存数量" prop="singleSkuStock">
|
|
|
+ <el-input-number v-model="form.singleSkuStock" :min="0" :step="1" />
|
|
|
</el-form-item>
|
|
|
</template>
|
|
|
- <el-form-item label="是否余额支付" prop="isBalancePay">
|
|
|
- <el-radio-group v-model="form.isBalancePay" size="small">
|
|
|
- <el-radio-button v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code">{{ dict.label }}</el-radio-button>
|
|
|
+
|
|
|
+ <!-- 多规格设置 -->
|
|
|
+ <template v-if="skuType === 1">
|
|
|
+ <!-- 规格项设置 -->
|
|
|
+ <div class="spec-group" v-for="(spec, index) in form.specList" :key="index">
|
|
|
+ <el-row :gutter="10">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="'规格项' + (index + 1)">
|
|
|
+ <el-input v-model="spec.name" placeholder="如: 颜色、尺码" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="14">
|
|
|
+ <el-form-item label="规格值">
|
|
|
+ <el-tag
|
|
|
+ :key="tag"
|
|
|
+ v-for="tag in spec.values"
|
|
|
+ closable
|
|
|
+ :disable-transitions="false"
|
|
|
+ @close="handleRemoveSpecValue(spec.values, tag)">
|
|
|
+ {{tag}}
|
|
|
+ </el-tag>
|
|
|
+ <el-input
|
|
|
+ class="input-new-tag"
|
|
|
+ v-if="spec.inputVisible"
|
|
|
+ v-model="spec.inputValue"
|
|
|
+ ref="saveTagInput"
|
|
|
+ size="small"
|
|
|
+ @keyup.enter.native="handleInputConfirm(spec)"
|
|
|
+ @blur="handleInputConfirm(spec)">
|
|
|
+ </el-input>
|
|
|
+ <el-button v-else class="button-new-tag" size="small" @click="showInput(spec)">
|
|
|
+ + 添加规格值
|
|
|
+ </el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="2">
|
|
|
+ <el-button type="text" @click="removeSpec(index)" icon="el-icon-delete">删除</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-button type="primary" plain @click="addSpec">添加规格项</el-button>
|
|
|
+
|
|
|
+ <!-- 规格组合列表 -->
|
|
|
+ <el-table :data="form.skuList" border style="margin-top: 20px">
|
|
|
+ <el-table-column
|
|
|
+ v-for="(spec, index) in form.specList"
|
|
|
+ :key="index"
|
|
|
+ :label="spec.name"
|
|
|
+ align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ {{scope.row.specs[index]}}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="销售价格" align="center" width="150">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input-number
|
|
|
+ v-model="scope.row.price"
|
|
|
+ :precision="2"
|
|
|
+ :step="0.1"
|
|
|
+ :min="0"
|
|
|
+ controls-position="right"
|
|
|
+ size="mini" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="库存" align="center" width="150">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input-number
|
|
|
+ v-model="scope.row.stock"
|
|
|
+ :min="0"
|
|
|
+ :step="1"
|
|
|
+ controls-position="right"
|
|
|
+ size="mini" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </template>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <!-- 其他设置 tab -->
|
|
|
+ <el-tab-pane label="其他设置" name="other">
|
|
|
+ <el-form-item label="促销标识" prop="isSell">
|
|
|
+ <el-radio-group v-model="form.isSell">
|
|
|
+ <el-radio-button v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code">
|
|
|
+ {{dict.label}}
|
|
|
+ </el-radio-button>
|
|
|
</el-radio-group>
|
|
|
</el-form-item>
|
|
|
- <!-- <el-form-item label="是否现金支付" prop="isCashPay">-->
|
|
|
- <!-- <el-radio-group v-model="form.isCashPay" size="small">-->
|
|
|
- <!-- <el-radio-button v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code">{{ dict.label }}</el-radio-button>-->
|
|
|
- <!-- </el-radio-group>-->
|
|
|
- <!-- </el-form-item>-->
|
|
|
- <!-- <template v-if="form.isCashPay === 'Y'">-->
|
|
|
- <!-- <el-form-item label="现金金额" prop="cashMoney">-->
|
|
|
- <!-- <el-input v-model="form.cashMoney" placeholder="请输入金额" />-->
|
|
|
- <!-- </el-form-item>-->
|
|
|
- <!-- </template>-->
|
|
|
- <el-form-item label="上传图片" prop="goodsImg">
|
|
|
- <image-upload v-model="form.goodsImg" />
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="上传图片集" prop="goodsImgs">
|
|
|
- <image-upload v-model="form.goodsImgs" :limit="limit" />
|
|
|
+
|
|
|
+ <el-form-item label="余额支付" prop="isBalancePay">
|
|
|
+ <el-radio-group v-model="form.isBalancePay">
|
|
|
+ <el-radio-button v-for="dict in dict.type.sys_yes_no" :label="dict.value" :key="dict.code">
|
|
|
+ {{dict.label}}
|
|
|
+ </el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
</el-form-item>
|
|
|
+
|
|
|
<el-form-item label="显示顺序" prop="sort">
|
|
|
- <el-input-number v-model="form.sort" placeholder="请输入显示顺序(升序排列显示)" :min="0" :step-strictly="true" :style="{ width: '100%' }"> </el-input-number>
|
|
|
- </el-form-item>
|
|
|
- <el-form-item label="商品简介" prop="goodsSynopsis">
|
|
|
- <editor v-model="form.goodsSynopsis" :min-height="192" />
|
|
|
+ <el-input-number v-model="form.sort" :min="0" :step="1" />
|
|
|
</el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-form>
|
|
|
- </el-row>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </el-form>
|
|
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
- <el-button type="primary" @click="submitForm" style="margin-left: 5%">提交</el-button>
|
|
|
+ <el-button type="primary" @click="submitForm">确 定</el-button>
|
|
|
<el-button @click="cancel">取 消</el-button>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
@@ -191,7 +303,31 @@ export default {
|
|
|
goodsType: null
|
|
|
},
|
|
|
// 表单参数
|
|
|
- form: {},
|
|
|
+ form: {
|
|
|
+ id: null,
|
|
|
+ goodsName: null,
|
|
|
+ goodsCategoryId: null,
|
|
|
+ goodsSynopsis: null,
|
|
|
+ brandId: null,
|
|
|
+ goodsImg: null,
|
|
|
+ goodsImgs: [],
|
|
|
+ goodsCode: null,
|
|
|
+ isSell: 'N',
|
|
|
+ isCashPay: 'Y',
|
|
|
+ cashMoney: null,
|
|
|
+ isBalancePay: 'Y',
|
|
|
+ createBy: null,
|
|
|
+ createById: null,
|
|
|
+ createTime: null,
|
|
|
+ updateBy: null,
|
|
|
+ updateById: null,
|
|
|
+ updateTime: null,
|
|
|
+ remark: null,
|
|
|
+ specList: [],
|
|
|
+ skuList: [],
|
|
|
+ singleSkuPrice: 0,
|
|
|
+ singleSkuStock: 0
|
|
|
+ },
|
|
|
// 表单校验
|
|
|
rules: {
|
|
|
goodsName: [
|
|
@@ -275,7 +411,9 @@ export default {
|
|
|
categoryList: {},
|
|
|
brandList: {},
|
|
|
goodsType: '',
|
|
|
- limit: 9
|
|
|
+ limit: 9,
|
|
|
+ activeTab: 'basic',
|
|
|
+ skuType: 0
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
@@ -333,7 +471,11 @@ export default {
|
|
|
updateBy: null,
|
|
|
updateById: null,
|
|
|
updateTime: null,
|
|
|
- remark: null
|
|
|
+ remark: null,
|
|
|
+ specList: [],
|
|
|
+ skuList: [],
|
|
|
+ singleSkuPrice: 0,
|
|
|
+ singleSkuStock: 0
|
|
|
}
|
|
|
this.resetForm('form')
|
|
|
},
|
|
@@ -380,22 +522,30 @@ export default {
|
|
|
},
|
|
|
/** 提交按钮 */
|
|
|
submitForm() {
|
|
|
- this.$refs['form'].validate((valid) => {
|
|
|
+ this.$refs['form'].validate(valid => {
|
|
|
if (valid) {
|
|
|
- if (this.form.isCashPay != 'Y') {
|
|
|
- this.form.cashMoney = '0'
|
|
|
+ const formData = { ...this.form }
|
|
|
+
|
|
|
+ // 处理SKU数据
|
|
|
+ if (this.skuType === 0) {
|
|
|
+ formData.skuList = [{
|
|
|
+ specs: [],
|
|
|
+ price: this.form.singleSkuPrice,
|
|
|
+ stock: this.form.singleSkuStock
|
|
|
+ }]
|
|
|
+ } else {
|
|
|
+ formData.skuList = this.form.skuList
|
|
|
}
|
|
|
- this.form.goodsType = this.goodsType
|
|
|
- if (this.form.id != null) {
|
|
|
- updateGoods(this.form).then((response) => {
|
|
|
+
|
|
|
+ // 提交数据
|
|
|
+ if (formData.id) {
|
|
|
+ updateGoods(formData).then(response => {
|
|
|
this.$modal.msgSuccess('修改成功')
|
|
|
this.open = false
|
|
|
this.getList()
|
|
|
})
|
|
|
} else {
|
|
|
- this.form.status = '0'
|
|
|
- this.form.delFlag = '0'
|
|
|
- addGoods(this.form).then((response) => {
|
|
|
+ addGoods(formData).then(response => {
|
|
|
this.$modal.msgSuccess('新增成功')
|
|
|
this.open = false
|
|
|
this.getList()
|
|
@@ -513,7 +663,118 @@ export default {
|
|
|
},
|
|
|
gotoComment(row) {
|
|
|
this.$router.push({ path: `/platform/goodsComment/appGoodsComment?goodsType=${this.goodsType}&goodsId=${row.id}` })
|
|
|
+ },
|
|
|
+ handleSkuTypeChange(val) {
|
|
|
+ if (val === 0) {
|
|
|
+ this.form.specList = []
|
|
|
+ this.form.skuList = []
|
|
|
+ } else {
|
|
|
+ // 如果已有规格数据,重新生成组合
|
|
|
+ if (this.form.specList.length > 0) {
|
|
|
+ this.generateSkuList()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ addSpec() {
|
|
|
+ this.form.specList.push({
|
|
|
+ name: '',
|
|
|
+ values: [],
|
|
|
+ inputVisible: false,
|
|
|
+ inputValue: ''
|
|
|
+ })
|
|
|
+ },
|
|
|
+ removeSpec(index) {
|
|
|
+ this.form.specList.splice(index, 1)
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.generateSkuList()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleRemoveSpecValue(values, tag) {
|
|
|
+ values.splice(values.indexOf(tag), 1)
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.generateSkuList()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ showInput(spec) {
|
|
|
+ spec.inputVisible = true
|
|
|
+ this.$nextTick(_ => {
|
|
|
+ this.$refs.saveTagInput.$refs.input.focus()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleInputConfirm(spec) {
|
|
|
+ let inputValue = spec.inputValue
|
|
|
+ if (inputValue && spec.values.indexOf(inputValue) === -1) {
|
|
|
+ spec.values.push(inputValue)
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.generateSkuList()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ spec.inputVisible = false
|
|
|
+ spec.inputValue = ''
|
|
|
+ },
|
|
|
+ generateSkuList() {
|
|
|
+ const specs = this.form.specList
|
|
|
+ if (specs.length === 0 || specs.some(spec => spec.values.length === 0)) {
|
|
|
+ this.form.skuList = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取所有规格值的组合
|
|
|
+ const values = specs.map(spec => spec.values)
|
|
|
+ const combinations = this.cartesianProduct(values)
|
|
|
+
|
|
|
+ // 保存现有的价格和库存数据
|
|
|
+ const existingSkus = this.form.skuList || []
|
|
|
+
|
|
|
+ // 生成新的SKU列表,保留已存在的价格和库存
|
|
|
+ this.form.skuList = combinations.map(specs => {
|
|
|
+ // 查找是否存在相同规格的旧数据
|
|
|
+ const existingSku = existingSkus.find(old =>
|
|
|
+ JSON.stringify(old.specs) === JSON.stringify(specs)
|
|
|
+ )
|
|
|
+
|
|
|
+ return {
|
|
|
+ specs,
|
|
|
+ price: existingSku ? existingSku.price : 0,
|
|
|
+ stock: existingSku ? existingSku.stock : 0
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ cartesianProduct(arrays) {
|
|
|
+ return arrays.reduce((a, b) => {
|
|
|
+ return a.map(x => {
|
|
|
+ return b.map(y => {
|
|
|
+ return Array.isArray(x) ? [...x, y] : [x, y]
|
|
|
+ })
|
|
|
+ }).flat()
|
|
|
+ }, [[]])
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.spec-group {
|
|
|
+ padding: 10px;
|
|
|
+ border: 1px solid #EBEEF5;
|
|
|
+ margin-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.el-tag + .el-tag {
|
|
|
+ margin-left: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.button-new-tag {
|
|
|
+ margin-left: 10px;
|
|
|
+ height: 32px;
|
|
|
+ line-height: 30px;
|
|
|
+ padding-top: 0;
|
|
|
+ padding-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.input-new-tag {
|
|
|
+ width: 90px;
|
|
|
+ margin-left: 10px;
|
|
|
+ vertical-align: bottom;
|
|
|
+}
|
|
|
+</style>
|