商城后台管理系统 02,上传图片实现

我们点击 '上传图片' 按钮,我们希望他弹出一个弹框,让我们选择上传图片,然后上传。
先把上传图片属性搞明白了,然后再开始上传操作
安装依赖
复制代码
1, 后台安装 multer 模块,同时引入 fs 文件模块

npm i multer -S

2, 在 router.js 入口文件导入模块
// 导入 multer
const multer = require('multer')

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

3, 配置 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
});


4, 上传图片 post 请求 upload 接口
/**
 * 上传图片 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
	});
});
上传图片实现 实现代码如下
复制代码
1, 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" @click="innerVisible=true">类目选择</el-button>
						<span>{{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">
						<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="即时配送" 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>
			<!-- 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';
	export default {
		components: {
			TreeGoods,
			UploadImg
		},
		// 接收父组件(Goods.vue)传值dialogVisible
		props: ['dialogVisible'],
		data() {
			return {
				// dialogVisible: false, // 外弹框
				innerVisible: false, // 内弹框
				innerVisibleImg: false, // 图片弹框
				treeData: {}, // 接收 tree 数据
				imgUrl: '', // 图片地址
				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: {
			// 显示图片地址
			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;
			},
			// 获取 tree 数据
			sendTreeData(val) {
				console.log('tree数据', val);
				this.treeData = val;
			},
			// 自定义事件--通知父组件--修改变量 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, src/views/Goods/UploadImg.vue
<template>
	<!-- 
	  ref="upload"	// 获取DOM元素 获取--upload 就可以使用upload的方法
	  action	// 必选参数,上传的地址
	  action="https://jsonplaceholder.typicode.com/posts/"
	  on-preview	// 点击文件列表中已上传的文件时的钩子 类型:function(file)
	  :on-preview="handlePreview"
	  on-remove	   // 文件列表移除文件时的钩子 类型:	function(file, fileList)
	  :on-remove="handleRemove"
	  file-list	   // 上传的文件列表  类型: Array  []
	  :file-list="fileList"
	  auto-upload	// 是否在选取文件后立即进行上传  类型:boolean 默认值为 true
	  :auto-upload="false">
	  on-success	// 文件上传成功时的钩子	function(response, file, fileList)
	  on-error	文件上传失败时的钩子	function(err, file, fileList)
	  on-progress	文件上传时的钩子	function(event, file, fileList)
	  on-change	文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用	function(file, fileList)
	  multiple	// 是否支持多选文件
	 -->
	<el-upload class="upload-demo" ref="upload" :action="url" :on-preview="handlePreview" :on-remove="handleRemove"
		:on-success="successUpload" :file-list="fileList" :auto-upload="false">
		<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
		<el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
		<!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> -->
	</el-upload>
</template>
<script>
	import base from '@/api/base.js'

	export default {

		data() {
			return {
				url: base.uploadUrl, // 图片地址服务器
				fileList: [],
				// fileList: [{
				// 	name: 'food.jpeg',
				// 	url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
				// }, {
				// 	name: 'food2.jpeg',
				// 	url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
				// }]
			};
		},
		methods: {
			// 点击 '上传图片' submit()	手动上传文件列表 按钮触发的事件 这个方法是当前库(elemnet-ui)提供的
			submitUpload() {
				this.$refs.upload.submit();
			},
			// 上传成功的函数
			successUpload(response, file, fileList) {
				console.log('上传成功', response, file, fileList);
				this.$message({
					message: '恭喜你,图片上传成功',
					type: 'success'
				});
				// 把成功的数据接口 response 传递给 父组件
				// http://localhost:8989/1764489007859-server-mesh7.png
				let imgUrl = base.host + '/' + response.url.slice(7);
				this.$emit('sendImg', imgUrl);
			},
			handleRemove(file, fileList) {
				console.log(file, fileList);
			},
			handlePreview(file) {
				console.log(file);
			}
		}
	}
</script>

<style>
</style>








3, 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请求
}

export default base;







4, src/api/index.js
// 搭建 express 服务
const express = require('express')

const app = express()

// post 请求表单数据
app.use(express.urlencoded({
	extended: true
}))

// 静态文件托管 --- 访问: http://localhost:8989/图片.jpg
app.use(express.static('upload'))

// 导入路由
const router = require('./router.js')
// 配置根路径
app.use('/api', router)

// 监听 
app.listen(8989, () => {
	console.log(8989);
})






5, 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
	});
});


module.exports = router

配置资源共享服务器端代码如下 server/index.js

复制代码
const express = require('express')
const app = express()

// post 请求表单数据
app.use(express.urlencoded({extended: true}))

// 资源共享
const cors = require('cors')
app.use(cors());

// 静态文件托管 --- 访问: http://localhost:8888/图片.jpg
app.use(express.static('upload'))

// 路由
const router = require('./router')
app.use('/',router)

// 监听
app.listen(8888,()=>{
	console.log(8888);
})
商品添加接口(后端代码)
复制代码
/**
* 商品添加接口
* 参数: title cid category sellPoint price num desc 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.desc || "";
	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: "添加失败"
			})
		}
	})
})
上传图片接口
复制代码
/**
 * 上传图片 post 请求 upload
 * 说明:
 * 1, 后台安装 multer 模块 同时引入 fs 模块
 * 2,router.js 入口文件导入 模块
 *	const fs = require('fs')
 *	const multer=require('multer')
 * 3, 上传图片 不能跨域 需要配置 cors index.js 导入文件,并配置 cors跨域
 */
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
	});
});
统计数据--销售信息接口
复制代码
/**
* 统计数据--销售信息
*/
router.get('/statistical', (req, res) => {
	res.send(Mock.mock({
		success: true,
		status: 200,
		"list|4": [
			{
				'id|+1': 100,
				"title|+1": ['总销售额','访问量','支付总量','收藏量'],
				"current|0-2000": 100,
				"total|100-999999": 200
			}
		]
	}))
})
内容分类管理 内容查询接口
复制代码
/**
* 内容分类管理 内容查询
*/
router.get("/content/selectTbContentAllByCategoryId", (req,res) =>{
	const pid = req.query.pid;
	const sql = "select * from contentinfo where pid=?"
	sqlFn(sql,[pid],result => {
		if (result.length > 0) {
			res.send({
				status: 200,
				result
			})
		} else {
			res.send({
				status: 500,
				msg: "暂无数据"
			})
		}
	})
})
相关推荐
破z晓2 小时前
若依(vue版)集成ArcGIS
前端·vue.js·arcgis
计算机学姐2 小时前
基于SSM的生鲜食品商城系统【2026最新】
java·vue.js·后端·mysql·java-ee·tomcat·mybatis
jinxinyuuuus2 小时前
FIRE之旅 财务计算器:实时交互式建模与前端性能工程
前端·人工智能·算法·自动化
Redundantº2 小时前
vuedraggable前端拖拽插件
前端
snow@li2 小时前
前端:软件开发中的秤砣理论 / 越简单越可靠 / 提炼组织架构 / 精确标定工作 / 有主干有支流 / 不追求繁琐 / 不做表面工作
前端·架构
张毫洁2 小时前
将后端resources中的文件返给前端下载的方法
前端·状态模式
Hao_Harrision2 小时前
50天50个小项目 (React19 + Tailwindcss V4) ✨| RandomChoicePicker(标签生成)
前端·typescript·react·vite7·tailwildcss
浮游本尊2 小时前
React 18.x 学习计划 - 第九天:React 18高级特性和最佳实践
前端·学习·react.js