一、开发准备
1. 环境确认
确保已经正确搭建若依开发环境,包括 JDK(建议 1.8 及以上)、Maven、Node.js、Vue CLI 等。同时,若依项目能够正常启动和访问。
2. 项目结构熟悉
再次熟悉若依项目的整体结构,特别是与业务开发相关的目录,例如:
ruoyi-admin
:后端管理模块,包含控制器、服务层、实体类等。ruoyi-ui
:前端项目,基于 Vue.js 构建,包含页面组件、API 接口封装等。
二、后端业务模块开发
1. 数据库设计
假设我们要创建一个 “商品管理” 业务模块,首先设计数据库表。在数据库中创建 tb_product
表,表结构如下:
sql
CREATE TABLE `tb_product` (
`product_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '商品 ID',
`product_name` varchar(200) NOT NULL COMMENT '商品名称',
`price` decimal(10, 2) NOT NULL COMMENT '商品价格',
`stock` int(11) NOT NULL COMMENT '商品库存',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';
2. 实体类创建
在 ruoyi-admin/src/main/java/com/ruoyi/system/domain
目录下创建 SysProduct
实体类,对应数据库中的 tb_product
表。
java
package com.ruoyi.system.domain;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
@Data
public class SysProduct extends BaseEntity {
private Long productId;
private String productName;
private Double price;
private Integer stock;
}
3. Mapper 接口与 XML 文件
- Mapper 接口:在
ruoyi-admin/src/main/java/com/ruoyi/system/mapper
目录下创建SysProductMapper
接口。
java
package com.ruoyi.system.mapper;
import com.ruoyi.system.domain.SysProduct;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SysProductMapper {
List<SysProduct> selectProductList(SysProduct product);
int insertProduct(SysProduct product);
int updateProduct(SysProduct product);
int deleteProductById(Long productId);
}
- XML 文件:在
ruoyi-admin/src/main/resources/mapper/system
目录下创建SysProductMapper.xml
文件,实现具体的 SQL 操作。
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.SysProductMapper">
<select id="selectProductList" resultType="com.ruoyi.system.domain.SysProduct">
SELECT * FROM tb_product
<where>
<if test="productName != null and productName != ''">
AND product_name LIKE CONCAT('%', #{productName}, '%')
</if>
</where>
</select>
<insert id="insertProduct">
INSERT INTO tb_product (product_name, price, stock)
VALUES (#{productName}, #{price}, #{stock})
</insert>
<update id="updateProduct">
UPDATE tb_product
SET product_name = #{productName},
price = #{price},
stock = #{stock}
WHERE product_id = #{productId}
</update>
<delete id="deleteProductById">
DELETE FROM tb_product WHERE product_id = #{productId}
</delete>
</mapper>
4. 服务层开发
在 ruoyi-admin/src/main/java/com/ruoyi/system/service
目录下创建 ISysProductService
接口和 SysProductServiceImpl
实现类。
java
// ISysProductService.java
package com.ruoyi.system.service;
import com.ruoyi.system.domain.SysProduct;
import java.util.List;
public interface ISysProductService {
List<SysProduct> selectProductList(SysProduct product);
int insertProduct(SysProduct product);
int updateProduct(SysProduct product);
int deleteProductById(Long productId);
}
// SysProductServiceImpl.java
package com.ruoyi.system.service.impl;
import com.ruoyi.system.domain.SysProduct;
import com.ruoyi.system.mapper.SysProductMapper;
import com.ruoyi.system.service.ISysProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SysProductServiceImpl implements ISysProductService {
@Autowired
private SysProductMapper productMapper;
@Override
public List<SysProduct> selectProductList(SysProduct product) {
return productMapper.selectProductList(product);
}
@Override
public int insertProduct(SysProduct product) {
return productMapper.insertProduct(product);
}
@Override
public int updateProduct(SysProduct product) {
return productMapper.updateProduct(product);
}
@Override
public int deleteProductById(Long productId) {
return productMapper.deleteProductById(productId);
}
}
5. 控制器开发
在 ruoyi-admin/src/main/java/com/ruoyi/system/controller
目录下创建 SysProductController
控制器。
java
package com.ruoyi.system.controller;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.SysProduct;
import com.ruoyi.system.service.ISysProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/system/product")
public class SysProductController extends BaseController {
@Autowired
private ISysProductService productService;
@GetMapping("/list")
public TableDataInfo list(SysProduct product) {
startPage();
List<SysProduct> list = productService.selectProductList(product);
return getDataTable(list);
}
@PostMapping
public AjaxResult add(@RequestBody SysProduct product) {
return toAjax(productService.insertProduct(product));
}
@PutMapping
public AjaxResult edit(@RequestBody SysProduct product) {
return toAjax(productService.updateProduct(product));
}
@DeleteMapping("/{productId}")
public AjaxResult remove(@PathVariable Long productId) {
return toAjax(productService.deleteProductById(productId));
}
}
三、前端业务模块开发
1. API 接口封装
在 ruoyi-ui/src/api/system
目录下创建 product.js
文件,封装与商品管理相关的 API 接口。
javascript
import request from '@/utils/request'
export function getProductList(query) {
return request({
url: '/system/product/list',
method: 'get',
params: query
})
}
export function addProduct(data) {
return request({
url: '/system/product',
method: 'post',
data: data
})
}
export function updateProduct(data) {
return request({
url: '/system/product',
method: 'put',
data: data
})
}
export function deleteProduct(productId) {
return request({
url: `/system/product/${productId}`,
method: 'delete'
})
}
2. 页面组件开发
在 ruoyi-ui/src/views/system
目录下创建 product
文件夹,并在其中创建 index.vue
文件,实现商品管理页面。
vue
<template>
<div>
<el-form :inline="true" :model="queryParams" class="demo-form-inline">
<el-form-item label="商品名称">
<el-input v-model="queryParams.productName" placeholder="请输入商品名称"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getProductList">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="productList" stripe>
<el-table-column prop="productId" label="商品 ID"></el-table-column>
<el-table-column prop="productName" label="商品名称"></el-table-column>
<el-table-column prop="price" label="商品价格"></el-table-column>
<el-table-column prop="stock" label="商品库存"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="editProduct(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" @click="deleteProduct(scope.row.productId)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :visible.sync="dialogVisible" title="商品信息">
<el-form :model="productForm">
<el-form-item label="商品名称">
<el-input v-model="productForm.productName"></el-input>
</el-form-item>
<el-form-item label="商品价格">
<el-input v-model="productForm.price"></el-input>
</el-form-item>
<el-form-item label="商品库存">
<el-input v-model="productForm.stock"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveProduct">保存</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getProductList, addProduct, updateProduct, deleteProduct } from '@/api/system/product'
export default {
data() {
return {
queryParams: {
productName: ''
},
productList: [],
dialogVisible: false,
productForm: {}
}
},
created() {
this.getProductList()
},
methods: {
getProductList() {
getProductList(this.queryParams).then(response => {
this.productList = response.rows
})
},
editProduct(row) {
this.productForm = { ...row }
this.dialogVisible = true
},
saveProduct() {
if (this.productForm.productId) {
updateProduct(this.productForm).then(response => {
if (response.code === 200) {
this.$message.success('更新成功')
this.dialogVisible = false
this.getProductList()
}
})
} else {
addProduct(this.productForm).then(response => {
if (response.code === 200) {
this.$message.success('添加成功')
this.dialogVisible = false
this.getProductList()
}
})
}
},
deleteProduct(productId) {
this.$confirm('确定要删除该商品吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteProduct(productId).then(response => {
if (response.code === 200) {
this.$message.success('删除成功')
this.getProductList()
}
})
})
}
}
}
</script>
3. 路由配置
在 ruoyi-ui/src/router/index.js
文件中添加商品管理页面的路由配置。
javascript
{
path: '/system/product',
component: Layout,
children: [
{
path: 'index',
name: 'ProductManagement',
component: () => import('@/views/system/product/index'),
meta: { title: '商品管理', icon: 'table' }
}
]
}
四、权限配置
1. 菜单配置
在系统管理 - 菜单管理中添加 “商品管理” 菜单,设置菜单名称、菜单类型、路由地址等信息,并关联到对应的角色。
2. 权限注解
在 SysProductController
控制器的方法上添加权限注解,例如:
java
@PreAuthorize("@ss.hasPermi('system:product:list')")
@GetMapping("/list")
public TableDataInfo list(SysProduct product) {
startPage();
List<SysProduct> list = productService.selectProductList(product);
return getDataTable(list);
}
五、测试与验证
1. 启动项目
分别启动若依后端和前端项目。
2. 功能测试
- 访问系统,使用具有 “商品管理” 权限的账号登录。
- 点击 “商品管理” 菜单,验证商品列表查询功能。
- 点击 “添加” 按钮,输入商品信息并保存,验证添加功能。
- 选择一条商品记录,点击 “编辑” 按钮,修改信息并保存,验证更新功能。
- 选择一条商品记录,点击 “删除” 按钮,确认删除,验证删除功能。
六、总结
通过本次二次开发,成功创建了一个 “商品管理” 业务模块,涵盖了后端的数据库设计、实体类、Mapper、服务层、控制器开发,以及前端的 API 封装、页面组件开发和路由配置。同时,进行了权限配置,确保不同角色用户对该模块的访问权限得到控制。在开发过程中,需要注意前后端接口的一致性和数据格式的匹配,同时合理使用若依框架提供的工具类和注解,提高开发效率。