若依学习日志03-二次开发-新建业务模块

一、开发准备

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 封装、页面组件开发和路由配置。同时,进行了权限配置,确保不同角色用户对该模块的访问权限得到控制。在开发过程中,需要注意前后端接口的一致性和数据格式的匹配,同时合理使用若依框架提供的工具类和注解,提高开发效率。

### 若依框架二次开发新增模块教程 #### 1. 准备工作 在开始之前,确保已经安装并配置好了必要的环境,包括但不限于Java开发环境、MySQL数据库以及IDEA集成开发环境。此外,还需下载并部署好若依框架的基础版本。 #### 2. 需求分析与规划 对于任何一次有效的软件开发活动而言,明确目标至关重要。这里假设要增加的是一个名为`UserActivityLog`的日记录功能模块,用于追踪用户的操作行为。这一步骤涉及确定该模块所需的核心业务逻辑及其与其他现有系统的交互方式[^2]。 #### 3. 数据库设计 根据所定义的需求,在MySQL中创建相应的数据表结构。例如: ```sql CREATE TABLE `sys_user_activity_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日ID', `user_id` varchar(64) DEFAULT '' COMMENT '用户编号', `operation_type` tinyint(4) DEFAULT NULL COMMENT '操作类型 (1=登录, 2=登出)', `ip_address` varchar(50) DEFAULT '' COMMENT 'IP地址', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) ); ``` 此SQL语句可以在IDEA内置的MySQL客户端工具内执行完成表单建立[^4]。 #### 4. 后端服务层构建 利用Spring Boot的强大特性快速搭建起RESTful API接口。具体来说就是编写Controller类接收HTTP请求并将处理后的响应返回给前端页面;Service层负责具体的业务流程控制;Mapper则用来映射实体对象到关系型数据库中的表格。 以下是部分简化版代码片段展示如何实现上述提到的服务端点之一——保存用户活动日信息至数据库的操作: ```java @RestController @RequestMapping("/api/user/activity-log") public class UserActivityLogController { @Autowired private IUserActivityLogService userActivityLogService; /** * 记录用户登录/退出事件. */ @PostMapping("/save") public ResponseEntity<?> save(@RequestBody SysUserActivityLog log){ try { this.userActivityLogService.save(log); return new ResponseEntity<>(HttpStatus.CREATED); } catch (Exception e) { logger.error(e.getMessage(),e); throw new RuntimeException("Failed to record activity."); } } } ``` 同时还需要配套的数据访问接口和服务实现类来支持以上API调用正常运作。 #### 5. 前端界面定制 借助Vue.js框架的优势可以轻松地为新加入的功能提供友好直观的人机交互体验。比如可以通过组件化的方式来组织UI布局,并且采用Vuex状态管理模式保持全局变量的一致性和可维护性。 下面是一个简单的例子说明怎样向导航栏菜单添加指向新建模块入口链接的过程: ```javascript // src/router/index.js import Vue from "vue"; import Router from "vue-router"; Vue.use(Router); export default new Router({ routes: [ ... { path: '/activity-log', name: 'Activity Log', component: () => import('@/views/UserActivityLog') }, ... ] }); ``` 另外还要记得更新左侧边栏对应的HTML模板文件以显示这个选项卡项。 #### 6. 测试验证 最后但同样重要的是进行全面而细致的质量检验环节。不仅要针对各个独立单元做白盒测试,也要考虑整个应用程序层面黑盒场景下的表现情况。只有经过充分验证之后才能放心上线发布新产品或特性改进成果[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值