RuoYi-Vue企业级实战:电商后台管理系统
RuoYi-Vue企业级实战:电商后台管理系统【免费下载链接】RuoYi-Vue???? 基于SpringBoot,Spring Security,JWT,Vue & Element 的前后端分离权限管理系统,同时提供了 Vue3 的版本...
·
RuoYi-Vue企业级实战:电商后台管理系统
前言:为什么选择RuoYi-Vue构建电商后台?
在数字化转型浪潮中,电商企业面临着后台管理系统开发效率低、权限控制复杂、系统稳定性要求高等痛点。传统开发模式往往需要从零开始搭建权限体系、日志监控、代码生成等基础功能,耗费大量开发资源。
RuoYi-Vue作为基于SpringBoot + Vue的前后端分离权限管理系统,提供了完整的解决方案。通过本文,您将掌握:
- ✅ 如何基于RuoYi-Vue快速搭建电商后台管理系统
- ✅ 电商核心业务模块的设计与实现
- ✅ 权限控制与数据安全的实战配置
- ✅ 代码生成器在电商开发中的高效应用
- ✅ 系统监控与性能优化的最佳实践
一、技术架构解析
1.1 整体架构设计
RuoYi-Vue采用经典的前后端分离架构,电商后台系统架构如下:
1.2 技术栈明细
| 层级 | 技术组件 | 版本 | 作用 |
|---|---|---|---|
| 前端 | Vue 2.x | 2.6.12 | 响应式UI框架 |
| 前端 | Element UI | 2.15.14 | UI组件库 |
| 前端 | Axios | 0.28.1 | HTTP客户端 |
| 后端 | Spring Boot | 2.5.15 | 微服务框架 |
| 后端 | Spring Security | 5.7.12 | 安全认证 |
| 后端 | JWT | 0.9.1 | Token认证 |
| 数据库 | MySQL | 5.7+ | 关系型数据库 |
| 缓存 | Redis | 5.0+ | 缓存数据库 |
| 监控 | Druid | 1.2.23 | 数据源监控 |
二、电商核心业务模块设计
2.1 数据库表结构设计
电商系统需要扩展以下核心表结构:
-- 商品分类表
CREATE TABLE `product_category` (
`category_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类ID',
`parent_id` bigint(20) DEFAULT '0' COMMENT '父分类ID',
`category_name` varchar(50) NOT NULL COMMENT '分类名称',
`level` int(1) DEFAULT '1' COMMENT '分类层级',
`sort` int(4) DEFAULT '0' COMMENT '排序',
`status` char(1) DEFAULT '0' COMMENT '状态(0正常 1停用)',
`icon` varchar(255) DEFAULT '' COMMENT '分类图标',
`keywords` varchar(255) DEFAULT '' COMMENT '关键词',
`description` varchar(500) DEFAULT '' COMMENT '描述',
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB COMMENT='商品分类表';
-- 商品信息表
CREATE TABLE `product_info` (
`product_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '商品ID',
`product_name` varchar(100) NOT NULL COMMENT '商品名称',
`category_id` bigint(20) NOT NULL COMMENT '分类ID',
`brand_id` bigint(20) DEFAULT NULL COMMENT '品牌ID',
`main_image` varchar(255) DEFAULT '' COMMENT '主图',
`sub_images` text COMMENT '副图',
`price` decimal(10,2) NOT NULL COMMENT '价格',
`market_price` decimal(10,2) DEFAULT NULL COMMENT '市场价',
`stock` int(11) NOT NULL DEFAULT '0' COMMENT '库存',
`weight` decimal(10,2) DEFAULT NULL COMMENT '重量',
`status` char(1) DEFAULT '0' COMMENT '状态(0上架 1下架)',
`detail` text COMMENT '商品详情',
`sale_count` int(11) DEFAULT '0' COMMENT '销量',
`view_count` int(11) DEFAULT '0' COMMENT '浏览量',
PRIMARY KEY (`product_id`)
) ENGINE=InnoDB COMMENT='商品信息表';
-- 订单表
CREATE TABLE `order_info` (
`order_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单ID',
`order_sn` varchar(64) NOT NULL COMMENT '订单编号',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`total_amount` decimal(10,2) NOT NULL COMMENT '订单总额',
`pay_amount` decimal(10,2) NOT NULL COMMENT '应付总额',
`freight_amount` decimal(10,2) DEFAULT '0.00' COMMENT '运费金额',
`pay_type` int(1) DEFAULT NULL COMMENT '支付方式',
`status` int(1) DEFAULT '0' COMMENT '状态',
`receiver_name` varchar(100) NOT NULL COMMENT '收货人姓名',
`receiver_phone` varchar(32) NOT NULL COMMENT '收货人电话',
`receiver_address` varchar(200) NOT NULL COMMENT '收货地址',
`note` varchar(500) DEFAULT '' COMMENT '订单备注',
`confirm_status` int(1) DEFAULT NULL COMMENT '确认状态',
`payment_time` datetime DEFAULT NULL COMMENT '支付时间',
`delivery_time` datetime DEFAULT NULL COMMENT '发货时间',
`receive_time` datetime DEFAULT NULL COMMENT '收货时间',
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB COMMENT='订单表';
2.2 前后端接口设计
基于RuoYi的RESTful API规范,电商接口设计示例:
// ProductController.java
@RestController
@RequestMapping("/product")
public class ProductController extends BaseController {
@Autowired
private IProductService productService;
/**
* 获取商品列表
*/
@PreAuthorize("@ss.hasPermi('product:list')")
@GetMapping("/list")
public TableDataInfo list(Product product) {
startPage();
List<Product> list = productService.selectProductList(product);
return getDataTable(list);
}
/**
* 新增商品
*/
@PreAuthorize("@ss.hasPermi('product:add')")
@Log(title = "商品管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody Product product) {
return toAjax(productService.insertProduct(product));
}
/**
* 修改商品
*/
@PreAuthorize("@ss.hasPermi('product:edit')")
@Log(title = "商品管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody Product product) {
return toAjax(productService.updateProduct(product));
}
}
前端API调用示例:
// product.js
import request from '@/utils/request'
// 查询商品列表
export function listProduct(query) {
return request({
url: '/product/list',
method: 'get',
params: query
})
}
// 新增商品
export function addProduct(data) {
return request({
url: '/product',
method: 'post',
data: data
})
}
// 修改商品
export function updateProduct(data) {
return request({
url: '/product',
method: 'put',
data: data
})
}
三、权限控制实战配置
3.1 菜单权限配置
在RuoYi系统中配置电商管理菜单:
-- 添加电商管理菜单
INSERT INTO sys_menu VALUES
('2000', '电商管理', '0', '5', 'ecommerce', null, '', '', 1, 0, 'M', '0', '0', '', 'shopping', 'admin', sysdate(), '', null, '电商管理目录'),
('2100', '商品管理', '2000', '1', 'product', 'ecommerce/product/index', '', '', 1, 0, 'C', '0', '0', 'ecommerce:product:list', 'goods', 'admin', sysdate(), '', null, '商品管理菜单'),
('2101', '商品查询', '2100', '1', '#', '', '', '', 1, 0, 'F', '0', '0', 'ecommerce:product:query', '#', 'admin', sysdate(), '', null, ''),
('2102', '商品新增', '2100', '2', '#', '', '', '', 1, 0, 'F', '0', '0', 'ecommerce:product:add', '#', 'admin', sysdate(), '', null, ''),
('2103', '商品修改', '2100', '3', '#', '', '', '', 1, 0, 'F', '0', '0', 'ecommerce:product:edit', '#', 'admin', sysdate(), '', null, ''),
('2104', '商品删除', '2100', '4', '#', '', '', '', 1, 0, 'F', '0', '0', 'ecommerce:product:remove', '#', 'admin', sysdate(), '', null, '');
3.2 数据权限配置
电商系统中的数据权限控制:
// 数据权限注解使用
@DataScope(deptAlias = "d", userAlias = "u")
public List<Product> selectProductList(Product product) {
return productMapper.selectProductList(product);
}
// 自定义权限校验
@Service("ps")
public class PermissionService {
/**
* 验证商品操作权限
*/
public boolean hasProductPermission(Long productId) {
// 获取当前用户
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userId = loginUser.getUserId();
// 查询用户是否有该商品的操作权限
// 这里可以根据业务需求实现具体的权限逻辑
return true;
}
}
// 在Controller中使用
@PreAuthorize("@ps.hasProductPermission(#productId)")
@DeleteMapping("/{productId}")
public AjaxResult remove(@PathVariable Long productId) {
return toAjax(productService.deleteProductById(productId));
}
四、代码生成器高效应用
4.1 生成电商业务代码
利用RuoYi代码生成器快速创建电商模块:
- 配置生成器参数:
# generator.yml
gen:
author: ecommerce
packageName: com.ruoyi.ecommerce
autoRemovePre: false
tablePrefix: ec_
- 生成步骤:
# 1. 在系统工具 -> 代码生成中导入表
# 2. 选择需要生成的表(如ec_product, ec_order等)
# 3. 编辑生成配置,设置模块名称为ecommerce
# 4. 生成代码并下载
# 5. 将生成的代码放入对应模块
- 生成的文件结构:
src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── ruoyi/
│ │ └── ecommerce/
│ │ ├── domain/Product.java
│ │ ├── mapper/ProductMapper.java
│ │ ├── service/IProductService.java
│ │ ├── service/impl/ProductServiceImpl.java
│ │ └── controller/ProductController.java
│ └── resources/
│ └── mapper/
│ └── ecommerce/
│ └── ProductMapper.xml
4.2 自定义模板优化
根据电商业务需求自定义生成模板:
## 在vm/java/domain.java.vm中添加电商特有字段
#if($table.subTables.size() > 0)
#foreach($subTable in $table.subTables)
/** $subTable.tableComment */
private List<${subTable.className}> ${subTable.classname}List;
#end
#end
## 电商特有字段
/** 商品销量 */
private Integer saleCount;
/** 商品浏览量 */
private Integer viewCount;
/** 商品状态(0上架 1下架) */
private String status;
五、前端组件开发实战
5.1 商品管理组件
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="100px">
<el-form-item label="商品名称" prop="productName">
<el-input
v-model="queryParams.productName"
placeholder="请输入商品名称"
clearable
style="width: 200px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="商品状态" prop="status">
<el-select v-model="queryParams.status" placeholder="商品状态" clearable style="width: 200px">
<el-option label="上架" value="0" />
<el-option label="下架" value="1" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
icon="el-icon-plus"
@click="handleAdd"
v-hasPermi="['ecommerce:product:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
icon="el-icon-edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['ecommerce:product:edit']"
>修改</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="productList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="商品ID" align="center" prop="productId" />
<el-table-column label="商品名称" align="center" prop="productName" />
<el-table-column label="价格" align="center" prop="price">
<template slot-scope="scope">
<span>¥{{ scope.row.price }}</span>
</template>
</el-table-column>
<el-table-column label="库存" align="center" prop="stock" />
<el-table-column label="销量" align="center" prop="saleCount" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">
{{ scope.row.status === '0' ? '上架' : '下架' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['ecommerce:product:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['ecommerce:product:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改商品对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="12">
<el-form-item label="商品名称" prop="productName">
<el-input v-model="form.productName" placeholder="请输入商品名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="商品分类" prop="categoryId">
<el-tree-select
v-model="form.categoryId"
:data="categoryOptions"
:props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
placeholder="请选择商品分类"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="商品价格" prop="price">
<el-input-number v-model="form.price" :min="0" :precision="2" />
</el-form-item>
<el-form-item label="商品库存" prop="stock">
<el-input-number v-model="form.stock" :min="0" />
</el-form-item>
<el-form-item label="商品状态">
<el-radio-group v-model="form.status">
<el-radio label="0">上架</el-radio>
<el-radio label="1">下架</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="商品主图">
<image-upload v-model="form.mainImage"/>
</el-form-item>
<el-form-item label="商品详情">
<editor v-model="form.detail" :min-height="192"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listProduct, getProduct, addProduct, updateProduct, delProduct } from "@/api/ecommerce/product";
import { listCategory } from "@/api/ecommerce/category";
export default {
name: "Product",
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 商品表格数据
productList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 分类选项
categoryOptions: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
productName: undefined,
status: undefined
},
// 表单参数
form: {},
// 表单校验
rules: {
productName: [
{ required: true, message: "商品名称不能为空", trigger: "blur" }
],
categoryId: [
{ required: true, message: "商品分类不能为空", trigger: "blur" }
],
price: [
{ required: true, message: "商品价格不能为空", trigger: "blur" }
]
}
};
},
created() {
this.getList();
this.getCategoryTree();
},
methods: {
/** 查询商品列表 */
getList() {
this.loading = true;
listProduct(this.queryParams).then(response => {
this.productList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 查询分类下拉树结构 */
getCategoryTree() {
listCategory().then(response => {
this.categoryOptions = this.handleTree(response.data, "categoryId", "parentId");
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
productId: undefined,
productName: undefined,
categoryId: undefined,
price: 0,
stock: 0,
status: "0",
mainImage: undefined,
detail: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.productId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加商品";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const productId = row.productId || this.ids;
getProduct(productId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改商品";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.productId != null) {
updateProduct(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addProduct(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const productIds = row.productId || this.ids;
this.$modal.confirm('是否确认删除商品编号为"' + productIds + '"的数据项?').then(function() {
return delProduct(productIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
}
};
</script>
六、系统监控与性能优化
6.1 电商系统监控配置
# application.yml 监控配置
spring:
datasource:
druid:
stat-view-servlet:
enabled: true
login-username: admin
login-password: 123456
web-stat-filter:
enabled: true
filter:
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 1000
# 自定义监控端点
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: always
6.2 性能优化策略
- 数据库优化:
-- 创建商品表索引
CREATE INDEX idx_product_category ON product_info(category_id);
CREATE INDEX idx_product_status ON product_info(status);
CREATE INDEX idx_product_name ON product_info(product_name);
-- 创建订单表索引
CREATE INDEX idx_order_user ON order_info(user_id);
CREATE INDEX idx_order_status ON order_info(status);
CREATE INDEX idx_order_time ON order_info(create_time);
- 缓存策略:
// 商品信息缓存配置
@Cacheable(value = "product", key = "#productId")
public Product getProductById(Long productId) {
return productMapper.selectProductById(productId);
}
// 分类信息缓存
@Cacheable(value = "category", key = "#categoryId")
public ProductCategory getCategoryById(Long categoryId) {
return categoryMapper.selectCategoryById(categoryId);
}
// 热门商品缓存
@Cacheable(value = "hotProducts", key = "'list'")
public List<Product> getHotProducts() {
return productMapper.selectHotProducts();
}
- 接口性能监控:
// 使用AOP监控接口性能
@Aspect
@Component
@Slf4j
public class PerformanceAspect {
@Around("execution(* com.ruoyi.ecommerce..*.*(..))")
public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
String methodName = joinPoint.getSignature().getName();
log.info("方法 {} 执行耗时: {}ms", methodName, (endTime - startTime));
// 记录慢查询
if (endTime - startTime > 1000) {
log.warn("慢接口警告: {} 耗时 {}ms", methodName, (endTime - startTime));
}
return result;
}
}
七、部署与运维指南
7.1 生产环境部署
# 后端部署脚本
#!/bin/bash
# deploy.sh
# 停止现有服务
echo "停止现有服务..."
pkill -f ruoyi-admin
# 备份旧版本
echo "备份旧版本..."
tar -czf /backup/ruoyi-$(date +%Y%m%d%H%M%S).tar.gz /app/ruoyi/
# 部署新版本
echo "部署新版本..."
unzip -o ruoyi-admin-3.9.0.jar -d /app/ruoyi/
# 启动服务
echo "启动服务..."
nohup java -jar /app/ruoyi/ruoyi-admin-3.9.0.jar \
--spring.profiles.active=prod \
--server.port=8080 \
> /app/ruoyi/ruoyi.log 2>&1 &
echo "部署完成!"
7.2 前端部署配置
// vue.config.js 生产环境配置
module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/ecommerce/' : '/',
outputDir: 'dist',
assetsDir: 'static',
lintOnSave: process.env.NODE_ENV === 'development',
productionSourceMap: false,
configureWebpack: {
externals: process.env.NODE_ENV === 'production' ? {
'vue': 'Vue',
'element-ui': 'ELEMENT'
} : {}
},
chainWebpack: config => {
config.plugin('html').tap(args => {
args[0].title = '电商后台管理系统';
return args;
});
// 配置CDN
if (process.env.NODE_ENV === 'production') {
config.plugin('html').tap(args => {
args[0].cdn = {
js: [
'https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js',
'https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/index.js'
],
css: [
'https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.14/theme-chalk/index.css'
]
};
return args;
});
}
}
};
更多推荐

所有评论(0)