商城后台管理系统 06,编辑商品

当我们点击'编辑'按钮,弹框不再叫添加商品,而叫编辑商品,同时,既然是编辑的话,我们点击了当前行编辑的数据,是不是得再弹框里面将当前行数据读出来,而不是置空,所以,当我们点击'编辑'按钮时,要把当前行的数据呈现在弹框上。
编辑商品 实现代码如下
复制代码
1,src/views/Layout/Mymenu.vue
<template>
	<div>
		<el-menu :default-active="$route.path" class="el-menu-vertical-demo" background-color="#545c64"
			text-color="#fff" active-text-color="#ffd04b" router :collapse="isCollapse">
			<el-menu-item>
				<i class="iconfont icon-icon_nav" style="color: skyblue;padding-right: 6px;font-size: 24px;"></i>
				<span slot="title">易购后台管理系统</span>
			</el-menu-item>
			<el-menu-item index="/">
				<i class="el-icon-menu"></i>
				<span slot="title">首页</span>
			</el-menu-item>
			<el-menu-item index="/goods">
				<i class="el-icon-document"></i>
				<span slot="title">商品管理</span>
			</el-menu-item>
			<el-menu-item index="/params">
				<i class="el-icon-setting"></i>
				<span slot="title">规格参数</span>
			</el-menu-item>
			<el-menu-item index="/advert">
				<i class="el-icon-setting"></i>
				<span slot="title">广告分类</span>
			</el-menu-item>
			<el-menu-item index="/my">
				<i class="el-icon-setting"></i>
				<span slot="title">个人中心</span>
			</el-menu-item>
			<el-menu-item index="/logistics">
				<i class="el-icon-setting"></i>
				<span slot="title">物流管理</span>
			</el-menu-item>
			<el-submenu index="/order">
				<template slot="title">
					<i class="el-icon-location"></i>
					<span>订单管理</span>
				</template>
				<el-menu-item-group>
					<template slot="title">订单</template>
					<el-menu-item index="/order/order-list">
						<i class="el-icon-document"></i>
						<span>订单列表</span>
					</el-menu-item>
					<el-menu-item index="/order/order-back">
						<i class="el-icon-setting"></i>
						<span>退货管理</span>
					</el-menu-item>
				</el-menu-item-group>
				<el-menu-item-group>
					<template slot="title">分组一</template>
					<el-menu-item index="5-3">选项1</el-menu-item>
					<el-menu-item index="5-4">选项2</el-menu-item>
				</el-menu-item-group>
				<el-menu-item-group title="分组2">
					<el-menu-item index="5-5">选项3</el-menu-item>
				</el-menu-item-group>
				<el-submenu index="1-4">
					<template slot="title">选项4</template>
					<el-menu-item index="1-4-1">选项1</el-menu-item>
				</el-submenu>
			</el-submenu>
		</el-menu>
	</div>
</template>

<script>
	export default {
		// 子组件Mymenu接收父组件(index)传递过来的数据
		props: ['isCollapse'],
		data() {
			return {
				// isCollapse: false
			};
		},
	};
</script>

<style lang="less" scoped>
	.el-menu {
		border-right: 0;

		.is-active {
			background: #1e78bf !important;
			color: #fff !important;
		}
	}

	.el-menu-vertical-demo:not(.el-menu--collapse) {
		width: 200px;
		min-height: 400px;
	}
</style>








2,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" sortable label="商品价格" width="120">
				</el-table-column>
				<el-table-column prop="num" sortable label="商品数量" width="120">
				</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="商品卖点" width="160" show-overflow-tooltip>
				</el-table-column>
				<el-table-column prop="descs" label="商品描述" show-overflow-tooltip>
				</el-table-column>
				<el-table-column label="操作" width="280">
					<template slot-scope="scope">
						<el-button size="mini">查看</el-button>
						<el-button type="primary" size="mini" @click="handleEdit(scope.$index, scope.row)"
							icon="el-icon-edit">编辑</el-button>
						<el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)"
							icon="el-icon-delete">删除</el-button>
					</template>
				</el-table-column>
			</el-table>
		</div>

		<!-- 全选--反选--批量删除 -->
		<div class="bottom">
			<el-button type="primary" size="small">全选</el-button>
			<el-button type="primary" size="small">反选</el-button>
			<el-button type="primary" size="small">批量删除</el-button>
		</div>

		<!-- 3, 分页展示  接收页码-->
		<MyPagination :total="total" :pageSize="pageSize" @changePage="changePage" :currentPage="currentPage" />

		<!-- 4, 显示弹框组件   :dialogVisible="dialogVisible"传值给子组件 GoodsDialog.vue-->
		<!-- 在调动资源的父组件位置 接收一个自定义事件 @changeDialog="changeDialog"-->
		<!--显示弹框组件  操作子组件:1, 父传子  2, children  3,ref -->
		<!-- <GoodsDialog :dialogVisible="dialogVisible" @changeDialog="changeDialog" /> -->
		<GoodsDialog ref='dialog' :title="title" :rowData="rowData" />
	</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,
				currentPage: 1, // 选中的高亮页码
				title: '添加商品', // 默认添加商品
				rowData: {}, // 当前行的数据--对象
			};
		},
		methods: {
			// 添加商品 -- 出现弹窗
			addGoods() {
				// 当点击 '弹框添加' 时,把变量dialogVisible赋值为true
				// this.dialogVisible = true;
				// 修改子组件实例的数据
				this.$refs.dialog.dialogVisible = true;
				this.title = '添加商品';
			},
			changeDialog() {
				this.dialogVisible = false;
			},
			// 分页的页码  搜索状态的分页
			changePage(num) {
				this.currentPage = 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);
					this.currentPage = 1;
					this.type = 1;
					return;
				}
				// console.log('搜索---', val);
				this.$api.getSearch({
					search: val
				}).then((res) => {
					console.log('搜索---', res.data);
					// 初始化为 1
					this.currentPage = 1;
					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;
						// this.currentPage = 1;
						console.log('分页', this.currentPage);
					} else {
						this.tableData = [];
						this.total = 1;
						this.pageSize = 1;
						this.type = 1;
						// this.currentPage = 1;
					}
				})
			},
			// 编辑操作
			handleEdit(index, row) { // row={} 每次都是一个新对象,都去赋值新地址
				// 1. 点击编辑按钮 显示弹框  // 2, 弹框上回显数据展示-当前行的数据
				this.$refs.dialog.dialogVisible = true;
				this.title = '编辑商品';
				// 每次赋值都是新地址
				this.rowData = {
					...row
				};
				// this.$refs.dialog.goodsForm = row; // 方法1
				//
			},
			// 删除操作
			handleDelete(index, row) {
				console.log('删除', index, row);
				this.$confirm('此操作将永久删除该商品, 是否继续?', '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				}).then(() => {
					// 请求接口
					this.$api.deleteGoods({
						// 前端传给后端的数据
						id: row.id
					}).then(res => {
						//
						console.log('删除', res.data);
						// 更新视图
						if (res.data.status === 200) {
							this.$message({
								type: 'success',
								message: '删除成功!'
							});
							// 视图更新
							this.http(1);
						}
					})
				}).catch(() => {
					this.$message({
						type: 'info',
						message: '已取消删除'
					});
				});
			},
			// 选择数据
			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;
	}
</style>







3,src/views/Goods/GoodsDialog.vue
<template>
	<div>
		<!-- 
		title="添加商品" 弹框的标题
		:visible.sync="dialogVisible" 控制弹框的显示与隐藏 boolean true 表示显示
		width="70%" 宽度 大小
		 -->
		<el-dialog :title="title" :visible.sync="dialogVisible" width="70%" :before-close="clearForm">
			<!-- 中间弹框内容区域 添加(修改)商品表单数据-->
			<el-form :model="goodsForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
				<el-form-item label="类目选择" prop="category">
					<el-button type="primary" @click="innerVisible=true">类目选择</el-button>
					<span style="margin-left: 10px;">{{goodsForm.category}}</span>
				</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" @click="innerVisibleImg=true">上传图片</el-button>
					<img :src="goodsForm.image" height="200px" style="margin-left: 10px;" alt="" />
				</el-form-item>
				<el-form-item label="商品描述" prop="descs">
					<!-- 父组件接收 sendEditor 数据 -->
					<WangEditor ref="myEditor" @sendEditor="sendEditor" />
				</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="即时配送" 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>
			<!-- 弹框的底部区域 -->
			<span slot="footer" class="dialog-footer">
				<!-- ref -->
				<el-button @click="clearForm">取消</el-button>
				<el-button type="primary" @click="submitForm">确 定</el-button>
				<!-- 父传子 -->
				<!-- <el-button @click="close">取消</el-button>
				<el-button type="primary" @click="close">确 定</el-button> -->
			</span>
			<!-- 1, 内弹框 --类目选择-->
			<el-dialog width="40%" title="类目选择" :visible.sync="innerVisible" append-to-body>
				<!-- 父组件接收 sendTreeData 数据 -->
				<TreeGoods @sendTreeData="sendTreeData" />

				<!-- 内弹框的底部区域 -->
				<span slot="footer" class="dialog-footer">
					<!-- ref -->
					<!-- <el-button @click="innerVisible = false">取 消</el-button>
					<el-button type="primary" @click="innerVisible = false">确 定</el-button> -->
					<!-- 父传子 -->
					<el-button @click="close">取消</el-button>
					<el-button type="primary" @click="showTreeData">确 定</el-button>
				</span>
			</el-dialog>
			<!-- 2, 内弹框 --上传图片-->
			<el-dialog width="40%" title="上传图片" :visible.sync="innerVisibleImg" append-to-body>
				<!-- 父组件接收 sendImg 数据 -->
				<UploadImg @sendImg="sendImg" />

				<!-- 内弹框的底部区域 -->
				<span slot="footer" class="dialog-footer">
					<!-- ref -->
					<el-button @click="innerVisibleImg = false">取 消</el-button>
					<el-button type="primary" @click="showImg">确 定</el-button>
					<!-- <el-button type="primary" @click="innerVisibleImg = false">确 定</el-button> -->
					<!-- 父传子 -->
					<!-- <el-button @click="close">取消</el-button>
					<el-button type="primary" @click="showTreeData">确 定</el-button> -->
				</span>
			</el-dialog>
		</el-dialog>
	</div>
</template>

<script>
	import TreeGoods from '@/views/Goods/TreeGoods.vue';
	import UploadImg from '@/views/Goods/UploadImg.vue';
	import WangEditor from '@/views/Goods/WangEditor.vue';
	export default {
		props: {
			title: {
				type: String,
				default: '添加商品'
			},
			rowData: {
				type: Object,
				default: function() {
					return {}
				}
			}
		},
		// mounted() { // 不行
		// 	console.log('生命周期--');
		// 	this.goodsForm = this.rowData;
		// },
		components: {
			TreeGoods,
			UploadImg,
			WangEditor
		},
		// 接收父组件(Goods.vue)传值dialogVisible
		// props: ['dialogVisible'],
		data() {
			return {
				dialogVisible: false, // 外弹框
				innerVisible: false, // 内弹框
				innerVisibleImg: false, // 图片弹框
				treeData: {}, // 接收 tree 数据
				imgUrl: '', // 图片地址
				goodsForm: { // 表单容器-对象
					id: '',
					title: '', // 商品的名称
					price: '', // 商品的价格
					num: '', // 商品的数量
					sellPoint: '', // 商品的卖点
					image: '', // 商品的图片
					descs: '', // 商品的描述
					cid: '', // 类目的id
					category: '', // 商品的类目
					// time: '', // 商品发布时间					
					date1: '',
					date2: '',
					// region: '',
					// 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'
					}]
				}
			};
		},
		// 监听器-----
		watch: {
			// 不要考虑老数据,直接拿当前的数据
			rowData(val) {
				console.log('监听到数据变化', val);
				// 赋值
				this.goodsForm = val;
				// 设置富文本编辑的数据内容  ref就是操作DOM
				// console.log('this.$refs.myEditor', this.$refs.myEditor);  // underfine
				this.$nextTick(() => {
					this.$refs.myEditor.editor.txt.html(val.descs);
					// console.log('this.$refs.myEditor', this.$refs.myEditor);
				})
			}
		},
		methods: {
			// 接收 wangEditor 数据
			sendEditor(val) {
				// 存储
				this.goodsForm.descs = val;
			},
			// 显示图片地址
			sendImg(val) {
				console.log('显示图片地址', val);
				this.imgUrl = val;
			},
			// 显示图片---确定按钮
			showImg() {
				// 让内弹框隐藏
				this.innerVisibleImg = false;
				// 渲染图片到页面
				this.goodsForm.image = this.imgUrl;
			},
			// 显示 tree 的数据
			showTreeData() {
				// 关闭内弹框
				this.innerVisible = false;
				// 显示 tree 数据
				this.goodsForm.category = this.treeData.name;
				this.goodsForm.cid = this.treeData.cid;
			},
			// 获取 tree 数据
			sendTreeData(val) {
				console.log('tree数据', val);
				this.treeData = val;
			},
			// 自定义事件--通知父组件--修改变量 dialogVisible
			close() {
				// 赋值
				// this.$emit('changeDialog', false);
				this.$emit('changeDialog');
			},
			submitForm() {
				this.$refs.ruleForm.validate((valid) => {
					if (valid) {
						console.log('获取输入的信息', this.goodsForm);
						// 结构赋值
						// title cid category sellPoint price num descs paramsInfo image
						let {
							title,
							cid,
							category,
							sellPoint,
							price,
							num,
							descs,
							// paramsInfo,
							image,
							id
						} = this.goodsForm;

						// 判断当前的确定按钮类型
						if (this.title === '添加商品') {
							console.log('添加商品');
							this.$api
								.addGoods({
									title,
									cid,
									category,
									sellPoint,
									price,
									num,
									descs,
									// paramsInfo,
									image,
									id
								})
								.then(res => {
									console.log('添加--实现--', res.data);
									if (res.data.status === 200) {
										// 成功 
										this.$parent.http(1); // 2,更新父组件列表数据
										this.$message({ // 3. 消息提示
											message: "恭喜你,添加商品成功",
											type: "success"
										});
										// 清空表单
										this.clearForm();
									} else {
										// 失败
										this.$message.error('错了,这是一条错误的消息');
									}
								});
						} else {
							console.log('编辑商品');
							this.$api.updateGoods({
									id,
									title,
									cid,
									category,
									sellPoint,
									price,
									num,
									descs,
									// paramsInfo,
									image,
									id
								})
								.then(res => {
									console.log(res.data);
									if (res.data.status === 200) {
										// 成功
										this.$parent.http(1); // 2,更新父组件列表数据
										this.$message({ // 3. 消息提示
											message: "恭喜你,修改商品成功",
											type: "success"
										});
										// 清空表单
										this.clearForm();
									} else {
										// 修改失败
										this.$message.error('错了,这是一条错误的消息');
									}
								})
						}
					} else {
						console.log('error submit!!');
						return false;
					}
				});
			},
			/**
			 * 清空表单数据列表
			 */
			clearForm() {
				this.dialogVisible = false; // 1,关闭弹框按钮

				// 4,清空表单
				// 4.1 使用 element 里面的重置表单
				// 4.2 自己手动初始化 goodsForm 表格数据
				// this.$refs.ruleForm.resetFields(); // 问题将商品描述里面的数据清空了
				this.goodsForm = {
					title: '', // 商品的名称
					price: '', // 商品的价格
					num: '', // 商品的数量
					sellPoint: '', // 商品的卖点
					image: '', // 商品的图片
					descs: '', // 商品的描述
					cid: '', // 类目的id
					category: '', // 商品的类目				
					date1: '', // 商品发布时间	
					date2: '', // 商品发布时间	
				}

				// 单独--清空编辑器内容--editor.txt.clear()
				this.$refs.myEditor.editor.txt.clear();
			}

			// resetForm(formName) {
			// 	this.$refs[formName].resetFields();
			// }
		}
	}
</script>

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

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






4, src/api/base.js  // 存放所有路径的文件
/**
 * 接口的路径配置:
 * 一般文件目录: base.js index.js
 * 	base.js : 放所有路径的配置
 *  index.js: 放所有请求的方法
 */

const base = {
	host: 'http://localhost:8989', // 基础域名
	goodsList: '/api/api/projectList', // 商品列表
	search: '/api/api/search', // 商品的搜索功能
	selectCategory: '/api/api/backend/itemCategory/selectItemCategoryByParentId', // 类目选择
	uploadUrl: '/api/api/upload', // 图片上传  post请求
	addGoods: '/api/api/backend/item/insertTbItem', // 添加商品 
	deleteGoods: '/api/api/backend/item/deleteItemById', // 删除商品
	updateGoods: '/api/api/backend/item/updateTbItem', // 编辑商品
}

export default base;






5, src/api/index.js	// 存放所有方法的文件
/**
 * 所有请求的方法
 */

import axios from "axios";
import base from "./base";
const api = {
	/**
	 * 商品列表方法
	 */
	getGoodsList(params) { // {page:xx}
		return axios.get(base.goodsList, {
			params
		})
	},
	/**
	 * 搜索商品数据方法
	 * search
	 */
	getSearch(params) { // {search: xx}
		return axios.get(base.search, {
			params
		})
	},
	/**
	 * 获取类目选择
	 * {id: cid}
	 */
	getSelectCategory(params) {
		return axios.get(base.selectCategory, {
			params
		})
	},
	/**
	 * 添加商品
	 * 参数: title cid category sellPoint price num desc paramsInfo image
	 */
	addGoods(params) { // = {}
		return axios.get(base.addGoods, {
			params
		})
	},
	/**
	 * 删除商品 id
	 */
	deleteGoods(params) {
		return axios.get(base.deleteGoods, {
			params
		})
	},
	/**
	 * 编辑商品 id
	 */
	updateGoods(params) {
		return axios.get(base.updateGoods, {
			params
		})
	},
}

export default api;





6, server/router.js	// 存放所有接口的文件
// 专门放所有的接口  这里只写一部分大约有二十几个接口

// 导入 express 
const express = require('express')
// 使用里面的 Router() 这个方法
const router = express.Router()

// 导入 multer
const multer = require('multer')

// 导入 fs
const fs = require('fs')

// token 
// const jwt = require('jsonwebtoken')

// 秘钥
// const config = require('./secert.js')

// 导入数据库 sqlFn('sql',[],res=>{})
const sqlFn = require('./mysql.js')

// 图片上传支持的模块
// const multer = require('multer')
// const fs = require('fs')


// 测试接口
// router.get('/', (req, res) => {
// 	res.send('hello')
// })

// 路由接口

// 登录接口
/**
 * 语法
 * 如 60,'2 day','10h','7d',expiration time 过期时间
 * jwt.sign({},'秘钥','过期时间',{expiresIn: 20*1,'1 day','1h'})
 */
/**
 * 登录 login
 */
// router.post('/login', (req, res) => {
// 	//
// })

/**
 * 注册接口 /register
 */
// router.post('/register', (req, res) => {
// 	//
// })

/**
 * 商品列表:获取分页 {total: '',arr:[{},{},{}],pagesize:8,}
 * 参数:page 页码
 */
router.get('/projectList', (req, res) => {
	const page = req.query.page || 1;
	const sqlLen = "select * from project where id";
	sqlFn(sqlLen, null, data => {
		let len = data.length;
		const sql = "select * from project order by id desc limit 8 offset" + (page - 1) * 8;
		sqlFn(sql, null, result => {
			if (result.length > 0) {
				res.send({
					status: 200,
					data: result,
					pageSize: 8,
					total: len
				})
			} else {
				res.send({
					status: 200,
					msg: "暂无数据"
				})
			}
		})
	})
})


// router.get('/projectList', (req, res) => {
// 	// 接收页码 可以不传 默认为1
// 	const page = req.query.page || 1;
// 	// 根据 id 去查 project 表
// 	const sqlLen = "select * from project where id";

// 	sqlFn(sqlLen, null, data => {
// 		let len = data.length;
// 		const sql = "select * from project order by id desc limit 8 offset" + (page - 1) * 8;
// 		sqlFn(sql, null, result => {
// 			if (result.length > 0) {
// 				// 返回数据
// 				res.send({
// 					status: 200,
// 					data: result,
// 					pageSize: 8,
// 					total: len
// 				})
// 			} else {
// 				// 返回数据
// 				res.send({
// 					status: 500,
// 					msg: "暂无数据"
// 				})
// 			}
// 		})
// 	})
// })


/**
 * 商品查询接口 search
 * 参数: search
 */
router.get("/search", (req, res) => {
	var search = req.query.search;
	const sql = "select * from project where concat(`title`,`sellPoint`,`descs`) like '%" + search + "%'";
	sqlFn(sql, null, (result) => {
		if (result.length > 0) {
			res.send({
				status: 200,
				data: result
			})
		} else {
			res.send({
				status: 500,
				msg: '暂无数据'
			})
		}
	})
})


/** 类目选择
 * 接口说明:接口不同的参数 cid 返回不同的类目数据,后台接受变量 id
 */
router.get('/backend/itemCategory/selectItemCategoryByParentId', (req, res) => {
	const id = req.query.id || 1;
	const sql = 'select * from category where id=?'
	var arr = [id];
	sqlFn(sql, arr, result => {
		if (result.length > 0) {
			res.send({
				status: 200,
				result
				// data: result
			})
		} else {
			res.send({
				status: 500,
				msg: '暂无数据'
			})
		}
	})
})


/**
 * 类目结构数据获取
 */
router.get('/category/data', (req, res) => {
	var cid = req.query.cid;
	var sql = "select * from params where itemCatId=?";
	sqlFn(sql, [cid], result => {
		if (result.length > 0) {
			res.send({
				status: 200,
				result
				// data: result
			})
		} else {
			res.send({
				status: 500,
				msg: '暂无数据'
			})
		}
	})
})


/**
 * 上传图片 post 请求 upload
 * 说明:
 * 1, 后台安装 multer 图片模块 同时引入 fs 文件模块  
 * 2,router.js 入口文件导入 模块
 *	const fs = require('fs')	//fs是属于nodejs,只需引入即可
 *	const multer=require('multer') // multer是需要安装的
 * 3, 上传图片 可以跨域 需要配置 cors index.js 导入文件,并配置 cors跨域
 * 4, 在服务端 server 根目录下创建 upload 文件夹,专门装图片的文件
 */
var storage = multer.diskStorage({
	destination: function(req, file, cb) {
		cb(null, './upload/')
	},
	filename: function(req, file, cb) {
		cb(null, Date.now() + "-" + file.originalname)
	}
})

var createFolder = function(folder) {
	try {
		fs.accessSync(folder);
	} catch (e) {
		fs.mkdirSync(folder);
	}
}

var uploadFolder = './upload';
createFolder(uploadFolder);
var upload = multer({
	storage: storage
});

router.post('/upload', upload.single('file'), function(req, res, next) {
	var file = req.file;
	console.log('文件类型,%s', file.mimetype);
	console.log('原始文件名,%s', file.originalname);
	console.log('文件大小,%s', file.size);
	console.log('文件保存路径,%s', file.path);
	res.json({
		res_code: '0',
		name: file.originalname,
		url: file.path
	});
});


/**
 * 商品添加接口
 * 参数: title cid category sellPoint price num descs paramsInfo image
 */
router.get('/backend/item/insertTbItem', (req, res) => {
	// 获取参数
	var title = req.query.title || "";
	var cid = req.query.cid || "";
	var category = req.query.category || "";
	var sellPoint = req.query.sellPoint || "";
	var price = req.query.price || "";
	var num = req.query.num || "";
	var desc = req.query.descs || "";
	var paramsInfo = req.query.paramsInfo || "";
	var image = req.query.image || "";

	const sql = "insert into project values (null,?,?,?,?,?,?,?,'',1,'','',?,?)"
	var arr = [title, image, sellPoint, price, cid, category, num, desc, paramsInfo];
	sqlFn(sql, arr, result => {
		if (result.affectedRows > 0) {
			res.send({
				status: 200,
				msg: "添加成功"
			})
		} else {
			res.send({
				status: 500,
				msg: "添加失败"
			})
		}
	})
})


/**
 * 商品删除 接口 id
 */
router.get("/backend/item/deleteItemById", (req, res) => {
	// 后端接收前端传递的数据
	var id = req.query.id;
	const sql = "delete from project where id=?"
	const arr = [id];
	sqlFn(sql, arr, result => {
		if (result.affectedRows > 0) {
			res.send({
				status: 200,
				msg: "删除成功"
			})
		} else {
			res.send({
				status: 500,
				msg: '删除失败'
			})
		}
	})
})


/**
 * 批量删除: batchDelete idArr id 标识
 * sql = "delete from A where in in (1,2,3)"
 */
router.get("/batchDelete", (req, res) => {
	let arr = req.query.idArr; // []数组格式 需要传递数据是 离散的数字格式
	// const sql = 'delete from project where id in (?)';
	let sql = '';

	function fun(arr) { // sql=`delete from project where id in (101,102,103`;
		sql = `delete from project where id in (`
		for (let i = 0; i < arr.length; i++) {
			sql += arr[i] + ',' // 101,102,
		}
		sql = sql.slice(0, -1)
		sql = sql + ')'
		// console.log(sql);
	}
	fun(arr)
	sqlFn(sql, null, result => {
		if (result.affectedRows > 0) {
			res.send({
				status: 200,
				msg: "删除成功"
			})
		} else {
			res.send({
				status: 500,
				msg: "删除失败"
			})
		}
	})



	/**
	 * 修改商品
	 */
	router.get("/backend/item/updateTbItem", (req, res) => {
		var id = req.query.id;
		var title = req.query.title || "";
		var sellPoint = req.query.sellPoint || "";
		var price = req.query.price || "";
		var cid = req.query.cid || "";
		var category = req.query.category || "";
		var num = req.query.num || "";
		var desc = req.query.descs || "";
		var paramsInfo = req.query.paramsInfo || "";
		var image = req.query.image || "";
		var sql =
			"update project set title=?,sellPoint=?,price=?,cid=?,category=?,num=?,descs=?,paramsInfo=?,image=?"
		var arr = [title, sellPoint, price, cid, category, num, descs, paramsInfo, image, id];
		sqlFn(sql, arr, result => {
			if (result.affectedRows > 0) {
				res.send({
					status: 200,
					msg: "修改成功"
				})
			} else {
				res.send({
					status: 500,
					msg: "修改失败"
				})
			}
		})
	})
})


module.exports = router
元素el: div#main dom元素
wangEditor属于第三方的工具需要单独处理 监听器拿不到他的数据

ref

监听器

相关推荐
qq_406176142 小时前
JavaScript中的循环特点和区别
开发语言·javascript·ecmascript
Aotman_2 小时前
JavaScript去除对象字段空格
开发语言·前端·javascript
我笔记2 小时前
Npm yarn 差异,冲突解决 依赖安装
vue.js
爱网安的monkey brother2 小时前
vue3+ts项目自建训练
前端·javascript·vue.js
哆啦A梦15882 小时前
商城后台管理系统 02,上传图片实现
前端·javascript·vue.js·elementui
破z晓2 小时前
若依(vue版)集成ArcGIS
前端·vue.js·arcgis
计算机学姐2 小时前
基于SSM的生鲜食品商城系统【2026最新】
java·vue.js·后端·mysql·java-ee·tomcat·mybatis
阿蒙Amon3 小时前
JavaScript学习笔记:5.函数
javascript·笔记·学习
How_doyou_do3 小时前
模态框与DOM,及React和Vue中的优化
前端·vue.js·react.js