Vue 商品管理模块(添加,修改)
商品添加功能点击添加商品展示编辑框因为添加商品代码比较多所以新建一个Add.vue组件index.js 中配置路由{path: '/goods',component: () =>import ('../components/goods/List.vue')},{path: '/goods/ad
商品添加功能
点击添加商品展示编辑框
因为添加商品代码比较多所以新建一个Add.vue组件
index.js 中配置路由
{
path: '/goods',
component: () =>
import ('../components/goods/List.vue')
},
{
path: '/goods/add',
component: () =>
import ('../components/goods/Add.vue')
},
]
<el-button type="primary" @click="goAddPage">添加商品</el-button>
// 点击添加商品跳转到添加商品页面
goAddPage(){
this.$router.push('/goods/add')
}
elementui 步骤条
<el-steps :active="active" finish-status="success">
<el-step title="步骤 1"></el-step>
<el-step title="步骤 2"></el-step>
<el-step title="步骤 3"></el-step>
</el-steps>
左侧的标签页
给tebs增加全局的样式 global.css
.el-steps {
margin: 15px 0;
}
.el-step__title {
font-size: 13px;
}
<!-- 提示信息 closable=>不能关闭的-->
<el-alert title="添加商品信息" type="info" show-icon :closable="false" center> </el-alert>
<!-- 步骤条 space 步骤条宽度-->
<el-steps :active="activeIndex" finish-status="success" align-center :space="200">
<el-step title="基本信息"></el-step>
<el-step title="商品参数"></el-step>
<el-step title="商品属性"></el-step>
<el-step title="商品图片"></el-step>
<el-step title="商品内容"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<!-- 标签页-->
<el-tabs tab-position="left" style="height: 200px">
<el-tab-pane label="基本信息">1</el-tab-pane>
<el-tab-pane label="商品参数">2</el-tab-pane>
<el-tab-pane label="商品属性">3</el-tab-pane>
<el-tab-pane label="商品图片">4</el-tab-pane>
<el-tab-pane label="商品内容">5</el-tab-pane>
</el-tabs>
效果
现在让标签页和步骤条关联起来
把标签页的取值和步骤条的取值设为一样的,就可以了
<!-- 提示信息 closable=>不能关闭的-->
<el-alert title="添加商品信息" type="info" show-icon :closable="false" center> </el-alert>
<!-- 步骤条 space 步骤条宽度-->
<el-steps :active="activeIndex" finish-status="success" align-center :space="200">
<el-step title="基本信息"></el-step>
<el-step title="商品参数"></el-step>
<el-step title="商品属性"></el-step>
<el-step title="商品图片"></el-step>
<el-step title="商品内容"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<!-- 标签页 这里的activeIndex 获取的就是name的值-->
<el-tabs v-model="activeIndex" tab-position="left" style="height: 200px">
<el-tab-pane label="基本信息" name="0">1</el-tab-pane>
<el-tab-pane label="商品参数" name="1">2</el-tab-pane>
<el-tab-pane label="商品属性" name="2">3</el-tab-pane>
<el-tab-pane label="商品图片" name="3">4</el-tab-pane>
<el-tab-pane label="商品内容" name="4">5</el-tab-pane>
</el-tabs>
这里会报错,需要数值0而不是字符串
获取的值随便减去一个数值js会隐式转换成数值
<!-- 步骤条 space 步骤条宽度-->
<el-steps :active="activeIndex-0" finish-status="success" align-center :space="200">
<template>
<div>
<!-- 面包屑导航-->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品管理</el-breadcrumb-item>
<el-breadcrumb-item>添加商品</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片试图-->
<el-card>
<!-- 提示信息 closable=>不能关闭的-->
<el-alert title="添加商品信息" type="info" show-icon :closable="false" center> </el-alert>
<!-- 步骤条 space 步骤条宽度-->
<el-steps :active="activeIndex-0" finish-status="success" align-center :space="200">
<el-step title="基本信息"></el-step>
<el-step title="商品参数"></el-step>
<el-step title="商品属性"></el-step>
<el-step title="商品图片"></el-step>
<el-step title="商品内容"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<!-- 标签页 这里的activeIndex 获取的就是name的值-->
<el-tabs v-model="activeIndex" tab-position="left" style="height: 200px">
<el-tab-pane label="基本信息" name="0">1</el-tab-pane>
<el-tab-pane label="商品参数" name="1">2</el-tab-pane>
<el-tab-pane label="商品属性" name="2">3</el-tab-pane>
<el-tab-pane label="商品图片" name="3">4</el-tab-pane>
<el-tab-pane label="商品内容" name="4">5</el-tab-pane>
</el-tabs>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
activeIndex: 0,
}
},
}
</script>
基本信息
控制label在输入框的上方
label-position='top'
限制输入的值是数值
v-model.number
<!-- 标签页 这里的activeIndex 获取的就是name的值-->
<el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="100px" label-position='top'>
<el-tabs v-model="activeIndex" tab-position="left">
<el-tab-pane label="基本信息" name="0">
<el-form-item label="商品名称" prop="goods_name">
<el-input v-model="addForm.goods_name"></el-input>
</el-form-item>
<el-form-item label="商品价格" prop="goods_price">
<el-input v-model.number="addForm.goods_name"></el-input>
</el-form-item>
<el-form-item label="商品重量" prop="goods_weight">
<el-input v-model.number="addForm.goods_name"></el-input>
</el-form-item>
<el-form-item label="商品数量" prop="goods_number">
<el-input v-model.number="addForm.goods_name"></el-input>
</el-form-item>
<el-form-item label="商品分类" >
</el-form-item>
</el-tab-pane>
<el-tab-pane label="商品参数" name="1">2</el-tab-pane>
<el-tab-pane label="商品属性" name="2">3</el-tab-pane>
<el-tab-pane label="商品图片" name="3">4</el-tab-pane>
<el-tab-pane label="商品内容" name="4">5</el-tab-pane>
</el-tabs>
</el-form>
elementui 级联选择器
<el-cascader
v-model="value"
:options="options"
:props="{ expandTrigger: 'hover' }"
@change="handleChange"></el-cascader>
响应的数据格式
{
"data": [
{
"cat_id": 1,
"cat_name": "大家电",
"cat_pid": 0,
"cat_level": 0,
"cat_deleted": false,
"children": [
{
"cat_id": 3,
"cat_name": "电视",
"cat_pid": 1,
"cat_level": 1,
"cat_deleted": false,
"children": [
{
"cat_id": 6,
"cat_name": "曲面电视",
"cat_pid": 3,
"cat_level": 2,
"cat_deleted": false
},
{
"cat_id": 7,
"cat_name": "海信",
"cat_pid": 3,
"cat_level": 2,
"cat_deleted": false
}
]
}
]
}
],
<el-form-item label="商品分类">
<el-cascader v-model="addForm.goods_cat" :options="cateList" :props="cascaderProps" @change="handleChange"></el-cascader>
</el-form-item>
<script>
export default {
data() {
return {
// 默认选中第0个
activeIndex: '0'
// 添加商品的表单对象
addForm: {
goods_name:'',
goods_price:null,
goods_weight:null,
goods_number:null,
// 商品分类数组
goods_cat:[]
},
addFormRules: {
goods_name: [{ required: true, message: '请输入商品名称', trigger: 'blur' }],
goods_price: [{ required: true, message: '请输入商品价格', trigger: 'blur' }],
goods_weight: [{ required: true, message: '请输入商品重量', trigger: 'blur' }],
goods_number: [{ required: true, message: '请输入商品数量', trigger: 'blur' }],
},
// 分类数组
cateList: [],
// 级联选择器的配置
cascaderProps:{
label:'cat_name',
value:'cat_id',
children:'children',
expandTrigger:'hover'
}
}
},
created() {
this.getCateList()
},
methods: {
// 获取分类列表
async getCateList() {
const { data: res } = await this.$http.get('categories')
if (res.meta.status !== 200) {
return this.$message.error('获取商品分类失败')
}
this.cateList = res.data
console.log(this.cateList)
},
// 监听级联选择器的改变事件
handleChange(){
}
},
}
</script>
<el-tabs v-model="activeIndex" tab-position="left" :before-leave="beforeTabLeave">
// 监听级联选择器的改变事件
handleChange(){
if(this.addForm.goods_cat.length!==3){
this.addForm.goods_cat = []
}
},
// tabs切换之前会触发 去往哪个标签页 oldActiveName之前的标签页
beforeTabLeave(activeName,oldActiveName){
if(this.addForm.goods_cat.length !==3){
this.$message.error('请先选择商品分类!')
return false
}
}
选择商品分类后要展示其商品参数和商品属性
elementui 中tab 被选中时触发,也就是进行切换的时候
<el-tabs v-model="activeIndex" tab-position="left" :before-leave="beforeTabLeave" @tab-click = "tabClicked">
获取动态参数和静态属性,对数据进行处理
// 动态参数
manyData:[],
// 静态参数
onlyData:[],
// tabs标签页切换时会执行 (显示商品的参数和属性)
async tabClicked(){
// 判断是否点击动态参数还是静态属性,因为点击其它的不需要
// 动态参数
if(this.activeIndex==='1'){
const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`,{
params:{sel:'many'}
})
if(res.meta.status !== 200){
return this.$message.error('获取动态参数失败')
}
res.data.forEach(item => {
item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
})
this.manyData=res.data
}
// 静态属性
else if(this.activeIndex==='2'){
const {data:res} = await this.$http.get(`categories/${this.cateId}/attributes`,{
params:{sel:'only'}
})
if(res.meta.status !== 200){
return this.$message.error('获取静态属性失败')
}
this.onlyData=res.data
}
}
},
computed:{
cateId(){
return this.addForm.goods_cat.length===3 ? this.addForm.goods_cat[2] : null
}
}
要展示商品参数
<el-tab-pane label="商品参数" name="1">
<el-form-item v-for="item in manyData" :key="item.attr_id" :label="item.attr_name">
<!-- 当前选中的数组 -->
<el-checkbox-group v-model="item.attr_vals">
<el-checkbox v-for="(value,i) in item.attr_vals" :key="i" :label="value" border></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-tab-pane>
<style scoped>
.el-checkbox{
margin-right: 10px;
}
</style>
静态属性
<el-tab-pane label="商品属性" name="2">
<el-form-item v-for="item in onlyData" :key="item.attr_id" :label="item.attr_name">
<el-input v-model="item.attr_vals"></el-input>
</el-form-item>
</el-tab-pane>
商品图片
action:服务器要上传后台API的地址
<el-upload
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="fileList"
list-type="picture">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
<el-tab-pane label="商品图片" name="3">
<!--action指定图片要上传的后台APL地址 handlePreview实现图片的预览 -->
<el-upload :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove" list-type="picture" :headers="headerObj">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</el-tab-pane>
</el-card>
<!-- 图片预览-->
<el-dialog title="图片预览" :visible.sync="previewVisible" width="50%" >
<img :src="previewPath" class="preview-img">
</el-dialog>
// 上传图片的URL地址
uploadUrl: '后台地址',
// 文件上传时请求头
headerObj: {
Authorization: JSON.parse(sessionStorage.getItem('userInfo')).token,
},
previewVisible:false,
// 展示图片的路径
previewPath:'',
// 图片预览
handlePreview(file) {
this.previewPath=file.url
this.previewVisible=true
},
使商品和图片产生关联,因为图片最终是要传递给后端的
<el-upload :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove" list-type="picture" :headers="headerObj" :on-success="handleSuccess">
// 添加商品的表单对象
addForm: {
goods_name: '',
goods_price: null,
goods_weight: null,
goods_number: null,
// 商品所属分类数组
goods_cat: [],
//图片的数组
pics:[],
},
// 移除图片回调
handleRemove(file) {
// 1.获取将要删除的图片的临时路径
const filePath = file.response.data.tmp_path
// 2. 从pics数组中找到这个图片对应的索引值
const i = this.addForm.pics.findIndex(item=>{
item.pic===filePath
})
// 3. 从pics数组中移除
this.addForm.pics.splice(i,1)
},
// 监听图片上传成功
handleSuccess(response){
this.addForm.pics.push({
pic:response.data.tmp_path
})
console.log(this.addForm)
},
实现富文本编辑器
基于Vue的Vue-Quill-Editor富文本编辑器
下载quill(Vue-Quill-Editor需要依赖)
npm install quill --save
下载Vue-Quill-Editor
npm install vue-quill-editor --save
main.js 中导入
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
Vue.component('QuillEditor', quillEditor)
main.js中
//导入富文本编辑器
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
Vue.use(VueQuillEditor)
global.css
.ql-editor {
min-height: 300px;
}
add_Form
// 富文本添加的说明(商品内容)
goods_introduce:''
<el-tab-pane label="商品内容" name="4">
<quill-editor v-model="addForm.goods_introduce"></quill-editor>
</el-tab-pane>
实现商品添加功能
商品内容填写完需要有一个添加商品的按钮
<el-tab-pane label="商品内容" name="4">
<quill-editor v-model="addForm.goods_introduce"></quill-editor>
<!--添加按钮-->
<el-button type="primary" class="btn-add">添加商品</el-button>
</el-tab-pane>
.btn-add{
margin-top: 15px;
}
准备请求前的数据
1.处理商品所属分类数组
不能直接将该数组直接用逗号转换,会导致级联选择器绑定的goods_cat发生异常
可以使用lodash 工具进行深拷贝
npm i -save lodash \\全局安装
引入
<script>
import _ from 'lodash'
export default {
<el-button type="primary" class="btn-add" @click="addGoods()">添加商品</el-button>
// 添加商品功能
addGoods(){
this.$refs.addFormRef.validate(async valid=>{
if(!valid){
return
}
// 准备请求前的数据
//1.处理商品所属分类数组
// 不能直接将该数组直接用逗号转换,会导致级联选择器绑定的goods_cat发生异常
// this,addForm.goods_cat = this.addForm.goods_cat.join(',')
// 可以使用lodash 工具进行深拷贝
const form = _.cloneDeep(this.addForm) // 深拷贝
form.goods_cat = form.goods_cat.join(',')
//处理动态参数
this.manyData.forEach(item=>{
form.attrs.push({
attr_id:item.attr_id,
attr_value:item.attr_vals.join(' ')
})
})
// 处理静态属性
this.onlyData.forEach(item=>{
form.attrs.push({
attr_id:item.attr_id,
attr_value:item.attr_vals
})
})
// 发送请求
const {data:res} = await this.$http.post('goods',form)
if(res.meta.status !== 201){
return this.$message.error('添加商品失败')
}
this.$message.success('添加商品成功!')
this.$router.push('/goods')
})
修改商品信息
编辑商品的页面和添加商品的页面一样,所以复制一个Add.vue
重命名为Edit.vue
index.js
{
path: '/goods/edit',
component: () =>
import ('../components/goods/Edit.vue')
},
在商品列表List.vue中实现路由的跳转到Edit.vue
<template slot-scope="scope">
<el-button size="mini" type="primary" icon="el-icon-edit" @click="geEditpage(scope.row.goods_id)"></el-button>
<el-button size="mini" type="danger" icon="el-icon-delete" @click="removeById(scope.row.goods_id)"></el-button>
// 跳转到修改商品页面
geEditpage(id){
this.$router.push('/goods/edit?id='+id)
}
Edit.vue
addForm 批量改为 editForm
created() {
this.getGoodsById()
},
根据id获取商品信息实现数据的回显
// 根据id获取商品信息
async getGoodsById(){
const{data:res} = await this.$http.get(`goods/${this.$route.query.id}`)
if(res.meta.status !== 200){
return this.$message.error('获取商品信息失败')
}
this.editForm=res.data
console.log(this.editForm)
},
此时会发现商品分类数据没有显示出来,因为后端返回的商品分类式字符串,实际上我们需要的数据类型式数组
// 对商品分类数据进行处理,转换为数组,此时数组中的元素还是字符串类型map再对数组中数据进行转换
res.data.goods_cat=res.data.goods_cat.split(',').map(item=>{
return item*1
此时图片也没有展示出来
返回的数据类型是这个造型
elementui 中 用以展示图片列表
<!--action指定图片要上传的后台APL地址 handlePreview实现图片的预览 -->
<el-upload :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove" list-type="picture" :headers="headerObj" :on-success="handleSuccess" :file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
在返回的图片数据中没有pic(图片的临时路径)这个属性,提交修改的时候需要跟之前一样
// 根据id获取商品信息
async getGoodsById(){
const{data:res} = await this.$http.get(`goods/${this.$route.query.id}`)
if(res.meta.status !== 200){
return this.$message.error('获取商品信息失败')
}
this.editForm=res.data
// 对商品分类数据进行处理,转换为数组,此时数组中的元素还是字符串类型map再对数组中数据进行转换
res.data.goods_cat=res.data.goods_cat.split(',').map(item=>{
return item*1
})
// 对图片数据进行处理 使其可以回显
res.data.pics.forEach(item=>{
this.fileList.push({
name:item.pics_id,
url:item.pics_big_url.replace('127.0.0.1','www.tangxiaoyang.vip'),
temp_path:item.pics_big
})
// 增加字段保存临时路径 这样在图片移除的时候就会包含临时路径
item.pic=item.pics_big
})
this.editForm=res.data
},
// 移除图片回调
handleRemove(file) {
// 1.获取将要删除的图片的临时路径 ()
// 服务器图片 新增图片
const filePath = file.tmp_path || file.response.data.tmp_path
// 2. 从pics数组中找到这个图片对应的索引值
const i = this.editForm.pics.findIndex(item=>{
item.pic===filePath
})
// 3. 从pics数组中移除
this.editForm.pics.splice(i,1)
},
// 修改商品功能
editGoods(){
this.$refs.editFormRef.validate(async valid=>{
if(!valid){
return
}
// 准备请求前的数据
//1.处理商品所属分类数组
// 不能直接将该数组直接用逗号转换,会导致级联选择器绑定的goods_cat发生异常
// this,editForm.goods_cat = this.editForm.goods_cat.join(',')
// 可以使用lodash 工具进行深拷贝
const form = _.cloneDeep(this.editForm) // 深拷贝
form.goods_cat = form.goods_cat.join(',')
//处理动态参数
this.manyData.forEach(item=>{
form.attrs.push({
attr_id:item.attr_id,
attr_value:item.attr_vals.join(' ')
})
})
// 处理静态属性
this.onlyData.forEach(item=>{
form.attrs.push({
attr_id:item.attr_id,
attr_value:item.attr_vals
})
})
// 发送请求
const {data:res} = await this.$http.post(`goods/${this.editForm.goods_id}`,form)
if(res.meta.status !== 200){
return this.$message.error('修改商品失败')
}
this.$message.success('修改商品成功!')
this.$router.push('/goods')
})
}
完整代码
<template>
<div>
<!-- 面包屑导航-->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品管理</el-breadcrumb-item>
<el-breadcrumb-item>修改商品</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片试图-->
<el-card>
<!-- 提示信息 closable=>不能关闭的-->
<el-alert title="修改商品信息" type="info" show-icon :closable="false" center> </el-alert>
<!-- 步骤条 space 步骤条宽度-->
<el-steps :active="activeIndex - 0" finish-status="success" align-center :space="200">
<el-step title="基本信息"></el-step>
<el-step title="商品参数"></el-step>
<el-step title="商品属性"></el-step>
<el-step title="商品图片"></el-step>
<el-step title="商品内容"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<!-- 标签页 这里的activeIndex 获取的就是name的值-->
<el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="100px" label-position="top">
<el-tabs v-model="activeIndex" tab-position="left" :before-leave="beforeTabLeave" @tab-click="tabClicked">
<el-tab-pane label="基本信息" name="0">
<el-form-item label="商品名称" prop="goods_name">
<el-input v-model="editForm.goods_name"></el-input>
</el-form-item>
<el-form-item label="商品价格" prop="goods_price">
<el-input v-model.number="editForm.goods_price" type="number"></el-input>
</el-form-item>
<el-form-item label="商品重量" prop="goods_weight" >
<el-input v-model.number="editForm.goods_weight" type="number"></el-input>
</el-form-item>
<el-form-item label="商品数量" prop="goods_number" >
<el-input v-model.number="editForm.goods_number" type="number"></el-input>
</el-form-item>
<el-form-item label="商品分类">
<el-cascader v-model="editForm.goods_cat" :options="cateList" :props="cascaderProps" @change="handleChange"></el-cascader>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="商品参数" name="1">
<el-form-item v-for="item in manyData" :key="item.attr_id" :label="item.attr_name">
<!-- 当前选中的数组 -->
<el-checkbox-group v-model="item.attr_vals">
<el-checkbox v-for="(value, i) in item.attr_vals" :key="i" :label="value" border></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="商品属性" name="2">
<el-form-item v-for="item in onlyData" :key="item.attr_id" :label="item.attr_name">
<el-input v-model="item.attr_vals"></el-input>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="商品图片" name="3">
<!--action指定图片要上传的后台APL地址 handlePreview实现图片的预览 -->
<el-upload :action="uploadUrl" :on-preview="handlePreview" :on-remove="handleRemove" list-type="picture" :headers="headerObj" :on-success="handleSuccess" :file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</el-tab-pane>
<el-tab-pane label="商品内容" name="4">
<quill-editor v-model="editForm.goods_introduce"></quill-editor>
<!--添加按钮-->
<el-button type="primary" class="btn-add" @click="editGoods()">修改商品</el-button>
</el-tab-pane>
</el-tabs>
</el-form>
</el-card>
<!-- 图片预览-->
<el-dialog title="图片预览" :visible.sync="previewVisible" width="50%" >
<img :src="previewPath" class="preview-img">
</el-dialog>
</div>
</template>
<script>
import _ from 'lodash'
export default {
data() {
return {
activeIndex: '0',
// 添加商品的表单对象
editForm: {
goods_name: '',
goods_price: null,
goods_weight: null,
goods_number: null,
// 商品所属分类数组
goods_cat: [],
//图片的数组
pics:[],
// 富文本添加的说明(商品内容)
goods_introduce:'',
// 商品的参数
attrs:[]
},
editFormRules: {
goods_name: [{ required: true, message: '请输入商品名称', trigger: 'blur' }],
goods_price: [{ required: true, message: '请输入商品价格', trigger: 'blur' }],
goods_weight: [{ required: true, message: '请输入商品重量', trigger: 'blur' }],
goods_number: [{ required: true, message: '请输入商品数量', trigger: 'blur' }],
},
// 分类数组
cateList: [],
// 级联选择器的配置
cascaderProps: {
label: 'cat_name',
value: 'cat_id',
children: 'children',
expandTrigger: 'hover',
},
// 动态参数
manyData: [],
// 静态参数
onlyData: [],
// 上传图片的URL地址
uploadUrl: 'http://www.tangxiaoyang.vip:8888/api/v2/upload',
// 文件上传时请求头
headerObj: {
Authorization: JSON.parse(sessionStorage.getItem('userInfo')).token,
},
previewVisible:false,
// 展示图片的路径
previewPath:'',
fileList:[]
}
},
created() {
this.getCateList()
this.getGoodsById()
},
methods: {
// 根据id获取商品信息
async getGoodsById(){
const{data:res} = await this.$http.get(`goods/${this.$route.query.id}`)
if(res.meta.status !== 200){
return this.$message.error('获取商品信息失败')
}
this.editForm=res.data
// 对商品分类数据进行处理,转换为数组,此时数组中的元素还是字符串类型map再对数组中数据进行转换
res.data.goods_cat=res.data.goods_cat.split(',').map(item=>{
return item*1
})
// 对图片数据进行处理 使其可以回显
res.data.pics.forEach(item=>{
this.fileList.push({
name:item.pics_id,
url:item.pics_big_url.replace('127.0.0.1','www.tangxiaoyang.vip'),
temp_path:item.pics_big
})
// 增加字段保存临时路径 这样在图片移除的时候就会包含临时路径
item.pic=item.pics_big
})
this.editForm=res.data
},
// 获取分类列表
async getCateList() {
const { data: res } = await this.$http.get('categories')
if (res.meta.status !== 200) {
return this.$message.error('获取商品分类失败')
}
this.cateList = res.data
},
// 监听级联选择器的改变事件
handleChange() {
if (this.editForm.goods_cat.length !== 3) {
this.editForm.goods_cat = []
}
},
// tabs切换之前会触发 去往哪个标签页 oldActiveName之前的标签页
beforeTabLeave(activeName, oldActiveName) {
if (this.editForm.goods_cat.length !== 3) {
this.$message.error('请先选择商品分类!')
return false
}
},
// tabs标签页切换时会执行 (显示商品的参数和属性)
async tabClicked() {
// 判断是否点击动态参数还是静态属性,因为点击其它的不需要
// 动态参数
if (this.activeIndex === '1') {
const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
params: { sel: 'many' },
})
if (res.meta.status !== 200) {
return this.$message.error('获取动态参数失败')
}
res.data.forEach((item) => {
item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
})
this.manyData = res.data
}
// 静态属性
else if (this.activeIndex === '2') {
const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`, {
params: { sel: 'only' },
})
if (res.meta.status !== 200) {
return this.$message.error('获取静态属性失败')
}
this.onlyData = res.data
}
},
// 图片预览
handlePreview(file) {
this.previewPath=file.url
this.previewVisible=true
},
// 移除图片回调
handleRemove(file) {
// 1.获取将要删除的图片的临时路径 ()
// 服务器图片 新增图片
const filePath = file.tmp_path || file.response.data.tmp_path
// 2. 从pics数组中找到这个图片对应的索引值
const i = this.editForm.pics.findIndex(item=>{
item.pic===filePath
})
// 3. 从pics数组中移除
this.editForm.pics.splice(i,1)
},
// 监听图片上传成功
handleSuccess(response){
this.editForm.pics.push({
pic:response.data.tmp_path
})
},
// 修改商品功能
editGoods(){
this.$refs.editFormRef.validate(async valid=>{
if(!valid){
return
}
// 准备请求前的数据
//1.处理商品所属分类数组
// 不能直接将该数组直接用逗号转换,会导致级联选择器绑定的goods_cat发生异常
// this,editForm.goods_cat = this.editForm.goods_cat.join(',')
// 可以使用lodash 工具进行深拷贝
const form = _.cloneDeep(this.editForm) // 深拷贝
form.goods_cat = form.goods_cat.join(',')
//处理动态参数
this.manyData.forEach(item=>{
form.attrs.push({
attr_id:item.attr_id,
attr_value:item.attr_vals.join(' ')
})
})
// 处理静态属性
this.onlyData.forEach(item=>{
form.attrs.push({
attr_id:item.attr_id,
attr_value:item.attr_vals
})
})
// 发送请求
const {data:res} = await this.$http.post(`goods/${this.editForm.goods_id}`,form)
if(res.meta.status !== 200){
return this.$message.error('修改商品失败')
}
this.$message.success('修改商品成功!')
this.$router.push('/goods')
})
}
},
computed: {
cateId() {
return this.editForm.goods_cat.length === 3 ? this.editForm.goods_cat[2] : null
},
},
}
</script>
<style scoped>
.el-checkbox {
margin-right: 10px;
}
.preview-img{
width: 100%;
}
.btn-add{
margin-top: 15px;
}
</style>
更多推荐
所有评论(0)