商城后台管理系统 02,商品-页面添加-弹框添加

我们将 '添加商品' 作为一个页面来展示

商品-页面添加-弹框添加 实现代码如下
复制代码
1, src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '@/views/Layout/index.vue'
import Home from '@/views/Home/index.vue'
import Login from '@/views/Login/Login.vue'

// 异步
const Goods = () => import('../views/Goods/Goods.vue')
const Params = () => import('../views/Params/Params.vue')
const Advert = () => import('../views/Advert/Advert.vue')
const My = () => import('../views/My/My.vue')
const Logistics = () => import('../views/Logistics/Logistics.vue')
const Order = () => import('../views/Order/index.vue')
const OrderList = () => import('../views/Order/OrderList/index.vue')
const OrderBack = () => import('../views/Order/OrderBack/index.vue')

// 子级路由
const AddGoods = () => import('../views/Goods/AddGoods.vue')


Vue.use(VueRouter)

const routes = [{
		path: '',
		component: Layout,
		children: [{
			path: '/',
			name: 'Home',
			component: Home
		}, {
			path: '/goods',
			name: 'Goods',
			component: Goods
		}, {
			path: '/add-goods',
			name: 'AddGoods',
			component: AddGoods
		}, {
			path: '/params',
			name: 'Params',
			component: Params
		}, {
			path: '/advert',
			name: 'Advert',
			component: Advert
		}, {
			path: '/my',
			name: 'My',
			component: My
		}, {
			path: '/logistics',
			name: 'Logistics',
			component: Logistics
		}, {
			path: '/order',
			name: 'Order',
			component: Order,
			redirect: '/order/order-list',
			children: [{
				path: 'order-list',
				component: OrderList
			}, {
				path: 'order-back',
				component: OrderBack
			}]
		}]
	},
	{
		path: '/login',
		name: 'Login',
		component: Login,
	}
]

const router = new VueRouter({
	mode: 'history',
	base: process.env.BASE_URL,
	routes
})

export default router






2, src/views/Goods/AddGoods.vue
<template>
	<div class="add-goods">
		<!-- 面包屑导航 -->
		<div class="title">
			<el-breadcrumb separator="/">
				<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
				<!-- <el-breadcrumb-item><a href="/goods">商品管理</a></el-breadcrumb-item> -->
				<el-breadcrumb-item :to="{ path: '/goods' }">商品管理</el-breadcrumb-item>
				<el-breadcrumb-item :to="{ path: '/params' }">规格参数</el-breadcrumb-item>
				<el-breadcrumb-item :to="{ path: '/advert' }">广告分类</el-breadcrumb-item>
				<el-breadcrumb-item :to="{ path: '/my' }">个人中心</el-breadcrumb-item>
				<el-breadcrumb-item :to="{ path: '/logistics' }">物流管理</el-breadcrumb-item>
				<el-breadcrumb-item :to="{ path: '/order' }">订单管理</el-breadcrumb-item>
				<el-breadcrumb-item :to="{ path: '/goods' }">添加商品</el-breadcrumb-item>
			</el-breadcrumb>
		</div>
		<!-- 添加商品表单数据 -->
		<div class="myform">
			<el-form :model="goodsForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
				<el-form-item label="类目选择" prop="category">
					<el-button type="primary">类目选择</el-button>
				</el-form-item>
				<el-form-item label="商品名称" prop="title">
					<el-input v-model="goodsForm.title"></el-input>
				</el-form-item>
				<el-form-item label="商品价格" prop="price">
					<el-input v-model="goodsForm.price"></el-input>
				</el-form-item>
				<el-form-item label="商品数量" prop="num">
					<el-input v-model="goodsForm.num"></el-input>
				</el-form-item>
				<el-form-item label="发布时间" required>
					<el-col :span="11">
						<el-form-item prop="date1">
							<el-date-picker type="date" placeholder="选择日期" v-model="goodsForm.date1"
								style="width: 100%;"></el-date-picker>
						</el-form-item>
					</el-col>
					<el-col class="line" :span="2">-</el-col>
					<el-col :span="11">
						<el-form-item prop="date2">
							<el-time-picker placeholder="选择时间" v-model="goodsForm.date2"
								style="width: 100%;"></el-time-picker>
						</el-form-item>
					</el-col>
				</el-form-item>
				<el-form-item label="商品卖点" prop="sellPoint">
					<el-input v-model="goodsForm.sellPoint"></el-input>
				</el-form-item>
				<el-form-item label="商品图片" prop="image">
					<el-button type="primary">商品图片</el-button>
				</el-form-item>
				<el-form-item label="商品描述" prop="descs">
					<textarea name="" id="" cols="30" rows="10"></textarea>
				</el-form-item>
				<el-form-item label="活动区域" prop="region">
					<el-select v-model="goodsForm.region" placeholder="请选择活动区域">
						<el-option label="区域一" value="shanghai"></el-option>
						<el-option label="区域二" value="beijing"></el-option>
					</el-select>
				</el-form-item>
				<!-- <el-form-item label="活动时间" required>
					<el-col :span="11">
						<el-form-item prop="date1">
							<el-date-picker type="date" placeholder="选择日期" v-model="goodsForm.date1"
								style="width: 100%;"></el-date-picker>
						</el-form-item>
					</el-col>
					<el-col class="line" :span="2">-</el-col>
					<el-col :span="11">
						<el-form-item prop="date2">
							<el-time-picker placeholder="选择时间" v-model="goodsForm.date2"
								style="width: 100%;"></el-time-picker>
						</el-form-item>
					</el-col>
				</el-form-item> -->
				<el-form-item label="即时配送" prop="delivery">
					<el-switch v-model="goodsForm.delivery"></el-switch>
				</el-form-item>
				<el-form-item label="活动性质" prop="type">
					<el-checkbox-group v-model="goodsForm.type">
						<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
						<el-checkbox label="地推活动" name="type"></el-checkbox>
						<el-checkbox label="线下主题活动" name="type"></el-checkbox>
						<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
					</el-checkbox-group>
				</el-form-item>
				<el-form-item label="特殊资源" prop="resource">
					<el-radio-group v-model="goodsForm.resource">
						<el-radio label="线上品牌商赞助"></el-radio>
						<el-radio label="线下场地免费"></el-radio>
					</el-radio-group>
				</el-form-item>
				<el-form-item label="活动形式" prop="desc">
					<el-input type="textarea" v-model="goodsForm.desc"></el-input>
				</el-form-item>
				<el-form-item>
					<el-button type="primary" @click="submitForm('goodsForm')">确定</el-button>
					<el-button @click="resetForm('goodsForm')">取消</el-button>
				</el-form-item>
			</el-form>
		</div>
	</div>
</template>

<script>
	export default {
		data() {
			return {
				goodsForm: { // 表单容器-对象
					title: '', // 商品的名称
					price: '', // 商品的价格
					num: '', // 商品的数量
					sellPoint: '', // 商品的卖点
					image: '', // 商品的图片
					descs: '', // 商品的描述
					category: '', // 商品的类目
					// time: '', // 商品发布时间
					region: '',
					date1: '',
					date2: '',
					delivery: false,
					type: [],
					resource: '',
					desc: ''
				},
				rules: { // 效验规则
					title: [{
							required: true,
							message: '请输入商品名称',
							trigger: 'blur'
						},
						{
							min: 2,
							max: 8,
							message: '长度在 2 到 8 个字符',
							trigger: 'blur'
						}
					],
					price: [{
							required: true,
							message: '请输入商品价格',
							trigger: 'blur'
						}
						// {
						// 	min: 3,
						// 	max: 5,
						// 	message: '长度在 3 到 5 个字符',
						// 	trigger: 'blur'
						// }
					],
					num: [{
							required: true,
							message: '请输入商品数量',
							trigger: 'blur'
						}
						// {
						// 	min: 3,
						// 	max: 5,
						// 	message: '长度在 3 到 5 个字符',
						// 	trigger: 'blur'
						// }
					],
					name: [{
							required: true,
							message: '请输入活动名称',
							trigger: 'blur'
						},
						{
							min: 3,
							max: 5,
							message: '长度在 3 到 5 个字符',
							trigger: 'blur'
						}
					],
					region: [{
						// required: true,
						message: '请选择活动区域',
						trigger: 'change'
					}],
					date1: [{
						type: 'date',
						required: true,
						message: '请选择日期',
						trigger: 'change'
					}],
					date2: [{
						type: 'date',
						required: true,
						message: '请选择时间',
						trigger: 'change'
					}],
					type: [{
						type: 'array',
						// required: true,
						message: '请至少选择一个活动性质',
						trigger: 'change'
					}],
					resource: [{
						// required: true,
						message: '请选择活动资源',
						trigger: 'change'
					}],
					desc: [{
						// required: true,
						message: '请填写活动形式',
						trigger: 'blur'
					}]
				}
			};
		},
		methods: {
			submitForm(formName) {
				this.$refs[formName].validate((valid) => {
					if (valid) {
						alert('submit!');
					} else {
						console.log('error submit!!');
						return false;
					}
				});
			},
			resetForm(formName) {
				this.$refs[formName].resetFields();
			}
		}
	}
</script>

<style lang="less" scoped>
	.add-goods {
		margin: 20px;
	}

	.title {
		padding: 10px;
		background: #fff;
		border: 1px solid #eee;
		margin-bottom: 20px;
	}

	.myform {
		background: #fff;
		padding: 20px;
		padding-right: 30px;
	}

	.line {
		text-align: center;
	}
</style>






3, src/views/Goods/Goods.vue

<template>
	<div class="goods">
		<!-- 1,搜索区域 -->
		<div class="header">
			<!-- 仅在输入框失去焦点或用户按下回车时触发 -->
			<el-input @change="searchInput" v-model="input" placeholder="请输入内容"></el-input>
			<el-button type="primary">查询</el-button>
			<!-- 页面添加 -->
			<el-button type="primary">
				<router-link to="/add-goods" style="color: #fff;">页面添加</router-link>
			</el-button>
			<!-- 弹窗添加 -->
			<el-button type="primary" @click="addGoods">弹框添加</el-button>
		</div>
		<!-- 2, 表格区域 展示视图数据  -->
		<div class="wrapper">
			<el-table :data="tableData" border @selection-change="handleSelectionChange">
				<el-table-column type="selection" width="55">
				</el-table-column>
				<el-table-column prop="id" label="商品ID" width="100">
				</el-table-column>
				<el-table-column prop="title" label="商品名称" width="100" show-overflow-tooltip>
				</el-table-column>
				<el-table-column prop="price" label="商品价格" width="100">
				</el-table-column>
				<el-table-column prop="num" label="商品数量" width="100">
				</el-table-column>
				<el-table-column prop="category" label="规格类目" width="100">
				</el-table-column>
				<el-table-column prop="image" label="商品图片" show-overflow-tooltip>
				</el-table-column>
				<el-table-column prop="sellPoint" label="商品卖点" show-overflow-tooltip>
				</el-table-column>
				<el-table-column prop="descs" label="商品描述" show-overflow-tooltip>
				</el-table-column>
				<el-table-column label="操作" width="180">
					<template slot-scope="scope">
						<el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
						<el-button size="mini" type="danger"
							@click="handleDelete(scope.$index, scope.row)">删除</el-button>
					</template>
				</el-table-column>
			</el-table>
		</div>

		<!-- 3, 分页展示  接收页码-->
		<MyPagination :total="total" :pageSize="pageSize" @changePage="changePage" />
		<!-- 4, 显示弹框组件   :dialogVisible="dialogVisible"传值给子组件 GoodsDialog.vue-->
		<!-- 在调动资源的父组件位置 接收一个自定义事件 @changeDialog="changeDialog"-->
		<!--显示弹框组件  操作子组件:1, 父传子  2, children  3,ref -->
		<GoodsDialog :dialogVisible="dialogVisible" @changeDialog="changeDialog" />
		<!-- <GoodsDialog ref='dialog' /> -->
	</div>
</template>

<script>
	import MyPagination from '@/components/MyPagination.vue';
	import GoodsDialog from '@/views/Goods/GoodsDialog.vue';
	export default {
		components: {
			MyPagination,
			GoodsDialog
		},
		data() {
			return {
				// 声明变量
				input: "",
				tableData: [],
				total: 10,
				pageSize: 1,
				type: 1,
				list: [],
				dialogVisible: false,
			}
		},
		methods: {
			// 添加商品 -- 出现弹窗
			addGoods() {
				// 当点击 '弹框添加' 时,把变量dialogVisible赋值为true
				this.dialogVisible = true;
				// 修改子组件实例的数据
				// this.$refs.dialog.dialogVisible = true;
			},
			changeDialog() {
				this.dialogVisible = false;
			},
			// 分页的页码  搜索状态的分页
			changePage(num) {
				if (this.type == 1) {
					this.http(num); // 商品列表分页
				} else {
					// 搜索分页 1,2,3-- list=[1,2,3,4,5,6,7,8]	0-3 3-6 6-9 9-12
					console.log('搜索的分页处理--', 截取分页的长度);
					// (num-1)*3 num*3  安装一个list容器
					this.tableData = this.list.slice((num - 1) * 3, num * 3);
				}
			},
			// 搜索查询的数据
			searchInput(val) {
				// 当没有搜索时,返回到商品列表页
				if (!val) {
					this.http(1);
					return;
				}
				// console.log('搜索---', val);
				this.$api.getSearch({
					search: val
				}).then(res => {
					console.log('搜索---', res.data);
					if (res.data.status === 200) {
						// 获取搜索总数据的条数---数据分割
						this.list = res.data.result;
						// 让前台匹配数据,这个数据就先不要赋值了
						// this.tableData = res.data.result;
						// 假设需要分页----我们处理分页
						// 1, 获取总数据
						this.total = res.data.result.length;
						// 2, 撤数据 正常情况下都是让后台匹配字段,我们这里让前台匹配
						this.pageSize = 3;
						// 3,赋值截取字段
						this.tableData = res.data.result.slice(0, 3);
						// 4, 搜索分页处理
						this.type = 2;
					} else {
						this.tableData = [];
						this.total = 1;
						this.pageSize = 1;
						this.type = 1;
					}
				})
			},
			// 编辑操作
			handleEdit() {},
			// 删除操作
			handleDelete() {},
			// 选择数据
			handleSelectionChange(val) {
				this.multipleSelection = val;
			},
			// 商品列表的获取 封装http 结构赋值
			http(page) {
				this.$api.getGoodsList({
					page,
				}).then((res) => {
					console.log('获取商品列表数据', res.data);
					if (res.data.status === 200) {
						// 数据列表
						this.tableData = res.data.data;
						this.total = res.data.total;
						this.pageSize = res.data.pageSize;
					}
				});
			},
		},
		// 生命周期函数
		created() {
			this.http(1);
		}
	};
</script>

<style lang="less" scoped>
	.goods {
		margin: 20px;
	}

	.header {
		display: flex;

		button {
			margin-left: 20px;
		}
	}

	.wrapper {
		margin: 20px 0;
	}

	// .pagination {
	// 	text-align: center;
	// 	margin: 20px;
	// }
</style>





4, src/views/Goods/GoodsDialog.vue
<template>
	<div>
		<!-- 
		title="添加商品" 弹框的标题
		:visible.sync="dialogVisible" 控制弹框的显示与隐藏 boolean true 表示显示
		width="70%" 宽度 大小
		 -->
		<el-dialog title="添加商品" :visible.sync="dialogVisible" width="70%">
			<!-- 中间弹框内容区域 -->
			<!-- 添加商品表单数据 -->
			<div class="myform">
				<el-form :model="goodsForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
					<el-form-item label="类目选择" prop="category">
						<el-button type="primary">类目选择</el-button>
					</el-form-item>
					<el-form-item label="商品名称" prop="title">
						<el-input v-model="goodsForm.title"></el-input>
					</el-form-item>
					<el-form-item label="商品价格" prop="price">
						<el-input v-model="goodsForm.price"></el-input>
					</el-form-item>
					<el-form-item label="商品数量" prop="num">
						<el-input v-model="goodsForm.num"></el-input>
					</el-form-item>
					<el-form-item label="发布时间" required>
						<el-col :span="11">
							<el-form-item prop="date1">
								<el-date-picker type="date" placeholder="选择日期" v-model="goodsForm.date1"
									style="width: 100%;"></el-date-picker>
							</el-form-item>
						</el-col>
						<el-col class="line" :span="2">-</el-col>
						<el-col :span="11">
							<el-form-item prop="date2">
								<el-time-picker placeholder="选择时间" v-model="goodsForm.date2"
									style="width: 100%;"></el-time-picker>
							</el-form-item>
						</el-col>
					</el-form-item>
					<el-form-item label="商品卖点" prop="sellPoint">
						<el-input v-model="goodsForm.sellPoint"></el-input>
					</el-form-item>
					<el-form-item label="商品图片" prop="image">
						<el-button type="primary">商品图片</el-button>
					</el-form-item>
					<el-form-item label="商品描述" prop="descs">
						<textarea name="" id="" cols="30" rows="10"></textarea>
					</el-form-item>
					<el-form-item label="活动区域" prop="region">
						<el-select v-model="goodsForm.region" placeholder="请选择活动区域">
							<el-option label="区域一" value="shanghai"></el-option>
							<el-option label="区域二" value="beijing"></el-option>
						</el-select>
					</el-form-item>
					<!-- <el-form-item label="活动时间" required>
						<el-col :span="11">
							<el-form-item prop="date1">
								<el-date-picker type="date" placeholder="选择日期" v-model="goodsForm.date1"
									style="width: 100%;"></el-date-picker>
							</el-form-item>
						</el-col>
						<el-col class="line" :span="2">-</el-col>
						<el-col :span="11">
							<el-form-item prop="date2">
								<el-time-picker placeholder="选择时间" v-model="goodsForm.date2"
									style="width: 100%;"></el-time-picker>
							</el-form-item>
						</el-col>
					</el-form-item> -->
					<el-form-item label="即时配送" prop="delivery">
						<el-switch v-model="goodsForm.delivery"></el-switch>
					</el-form-item>
					<el-form-item label="活动性质" prop="type">
						<el-checkbox-group v-model="goodsForm.type">
							<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
							<el-checkbox label="地推活动" name="type"></el-checkbox>
							<el-checkbox label="线下主题活动" name="type"></el-checkbox>
							<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
						</el-checkbox-group>
					</el-form-item>
					<el-form-item label="特殊资源" prop="resource">
						<el-radio-group v-model="goodsForm.resource">
							<el-radio label="线上品牌商赞助"></el-radio>
							<el-radio label="线下场地免费"></el-radio>
						</el-radio-group>
					</el-form-item>
					<el-form-item label="活动形式" prop="desc">
						<el-input type="textarea" v-model="goodsForm.desc"></el-input>
					</el-form-item>
					<!-- <el-form-item>
						<el-button type="primary" @click="submitForm('goodsForm')">确定</el-button>
						<el-button @click="resetForm('goodsForm')">取消</el-button>
					</el-form-item> -->
				</el-form>
			</div>
			<!-- 弹框的底部区域 -->
			<span slot="footer" class="dialog-footer">
				<!-- ref -->
				<!-- <el-button @click="dialogVisible = false">取 消</el-button>
				<el-button type="primary" @click="dialogVisible = false">确 定</el-button> -->
				<!-- 父传子 -->
				<el-button @click="close">取消</el-button>
				<el-button type="primary" @click="close">确 定</el-button>
			</span>
		</el-dialog>
	</div>
</template>

<script>
	export default {
		// 接收父组件(Goods.vue)传值dialogVisible
		props: ['dialogVisible'],
		data() {
			return {
				// dialogVisible: false,
				goodsForm: { // 表单容器-对象
					title: '', // 商品的名称
					price: '', // 商品的价格
					num: '', // 商品的数量
					sellPoint: '', // 商品的卖点
					image: '', // 商品的图片
					descs: '', // 商品的描述
					category: '', // 商品的类目
					// time: '', // 商品发布时间
					region: '',
					date1: '',
					date2: '',
					delivery: false,
					type: [],
					resource: '',
					desc: ''
				},
				rules: { // 效验规则
					title: [{
							required: true,
							message: '请输入商品名称',
							trigger: 'blur'
						},
						{
							min: 2,
							max: 8,
							message: '长度在 2 到 8 个字符',
							trigger: 'blur'
						}
					],
					price: [{
							required: true,
							message: '请输入商品价格',
							trigger: 'blur'
						}
						// {
						// 	min: 3,
						// 	max: 5,
						// 	message: '长度在 3 到 5 个字符',
						// 	trigger: 'blur'
						// }
					],
					num: [{
							required: true,
							message: '请输入商品数量',
							trigger: 'blur'
						}
						// {
						// 	min: 3,
						// 	max: 5,
						// 	message: '长度在 3 到 5 个字符',
						// 	trigger: 'blur'
						// }
					],
					name: [{
							required: true,
							message: '请输入活动名称',
							trigger: 'blur'
						},
						{
							min: 3,
							max: 5,
							message: '长度在 3 到 5 个字符',
							trigger: 'blur'
						}
					],
					region: [{
						// required: true,
						message: '请选择活动区域',
						trigger: 'change'
					}],
					date1: [{
						type: 'date',
						required: true,
						message: '请选择日期',
						trigger: 'change'
					}],
					date2: [{
						type: 'date',
						required: true,
						message: '请选择时间',
						trigger: 'change'
					}],
					type: [{
						type: 'array',
						// required: true,
						message: '请至少选择一个活动性质',
						trigger: 'change'
					}],
					resource: [{
						// required: true,
						message: '请选择活动资源',
						trigger: 'change'
					}],
					desc: [{
						// required: true,
						message: '请填写活动形式',
						trigger: 'blur'
					}]
				}
			};
		},
		methods: {
			// 自定义事件--通知父组件--修改变量 dialogVisible
			close() {
				// 赋值
				// this.$emit('changeDialog', false);
				this.$emit('changeDialog');
			},
			submitForm(formName) {
				this.$refs[formName].validate((valid) => {
					if (valid) {
						alert('submit!');
					} else {
						console.log('error submit!!');
						return false;
					}
				});
			},
			resetForm(formName) {
				this.$refs[formName].resetFields();
			}
		}
	}
</script>

<style lang="less" scoped>
	.myform {
		background: #fff;
		padding: 20px;
		padding-right: 30px;
	}

	.line {
		text-align: center;
	}
</style>
相关推荐
小胖霞2 小时前
vite+ts+monorepo从0搭建vue3组件库(五):vite打包组件库
前端·vue.js·前端框架
Java陈序员2 小时前
一键部署!一款开源自托管的照片画廊神器!
vue.js·docker
AAA阿giao2 小时前
从“拼字符串”到“魔法响应”:一场数据驱动页面的奇幻进化之旅
前端·javascript·vue.js
donecoding2 小时前
解决 npm 发布 403 错误:全局配置 NPM Automation Token 完整指南
前端·javascript
小胖霞2 小时前
vite+ts+monorepo从0搭建vue3组件库(三):开发一个组件
vue.js·前端框架·前端工程化
JS_GGbond3 小时前
Vue3 组件入门:像搭乐高一样玩转前端!
前端·vue.js
SakuraOnTheWay3 小时前
拆解一个由 setTimeout 引发的“页面假死”悬案
前端·javascript
小胖霞3 小时前
vite+ts+monorepo从0搭建vue3组件库(二):项目搭建
前端·vue.js·前端工程化
小胖霞3 小时前
vite+ts+monorepo从0搭建vue3组件库(四):button组件开发
vue.js·前端框架·前端工程化