若依框架学习日志04-二次开发-菜品管理

若依框架学习日志 04 - 二次开发 - 菜品管理

一、需求理解与规划

1. 需求分析

本次要开发的菜品管理模块,主要功能包括菜品信息的增删改查,同时要关联菜品分类和图片信息。用户可以根据菜品名称、分类等条件查询菜品列表,对单个菜品进行详细信息的查看、修改和删除操作,并且能够上传菜品图片。

2. 功能规划

  • 菜品列表展示:显示菜品的基本信息,如菜品名称、价格、所属分类等。
  • 菜品添加:输入菜品的详细信息,选择所属分类,上传菜品图片。
  • 菜品编辑:修改已存在菜品的信息。
  • 菜品删除:删除指定的菜品记录。
  • 菜品查询:支持按菜品名称、分类进行模糊查询。

二、数据库设计

1. 菜品表(tb_dish

sql

CREATE TABLE `tb_dish` (
    `dish_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '菜品 ID',
    `dish_name` varchar(200) NOT NULL COMMENT '菜品名称',
    `price` decimal(10, 2) NOT NULL COMMENT '菜品价格',
    `category_id` bigint(20) NOT NULL COMMENT '菜品分类 ID',
    `image_url` varchar(500) DEFAULT NULL COMMENT '菜品图片 URL',
    `description` text COMMENT '菜品描述',
    `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`dish_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜品表';

2. 菜品分类表(tb_dish_category

sql

CREATE TABLE `tb_dish_category` (
    `category_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类 ID',
    `category_name` varchar(100) NOT NULL COMMENT '分类名称',
    `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜品分类表';

三、后端开发

1. 实体类创建

  • Dish 实体类:在 ruoyi-admin/src/main/java/com/ruoyi/system/domain 目录下创建 SysDish 类。

java

package com.ruoyi.system.domain;

import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;

@Data
public class SysDish extends BaseEntity {
    private Long dishId;
    private String dishName;
    private Double price;
    private Long categoryId;
    private String imageUrl;
    private String description;
}

  • DishCategory 实体类:同样在该目录下创建 SysDishCategory 类。

java

package com.ruoyi.system.domain;

import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;

@Data
public class SysDishCategory extends BaseEntity {
    private Long categoryId;
    private String categoryName;
}

2. Mapper 接口与 XML 文件

  • DishMapper 接口:在 ruoyi-admin/src/main/java/com/ruoyi/system/mapper 目录下创建 SysDishMapper 接口。

java

package com.ruoyi.system.mapper;

import com.ruoyi.system.domain.SysDish;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface SysDishMapper {
    List<SysDish> selectDishList(SysDish dish);
    int insertDish(SysDish dish);
    int updateDish(SysDish dish);
    int deleteDishById(Long dishId);
}

  • DishMapper XML 文件:在 ruoyi-admin/src/main/resources/mapper/system 目录下创建 SysDishMapper.xml 文件。

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.SysDishMapper">
    <select id="selectDishList" resultType="com.ruoyi.system.domain.SysDish">
        SELECT * FROM tb_dish
        <where>
            <if test="dishName != null and dishName != ''">
                AND dish_name LIKE CONCAT('%', #{dishName}, '%')
            </if>
            <if test="categoryId != null">
                AND category_id = #{categoryId}
            </if>
        </where>
    </select>
    <insert id="insertDish">
        INSERT INTO tb_dish (dish_name, price, category_id, image_url, description)
        VALUES (#{dishName}, #{price}, #{categoryId}, #{imageUrl}, #{description})
    </insert>
    <update id="updateDish">
        UPDATE tb_dish
        SET dish_name = #{dishName},
            price = #{price},
            category_id = #{categoryId},
            image_url = #{imageUrl},
            description = #{description}
        WHERE dish_id = #{dishId}
    </update>
    <delete id="deleteDishById">
        DELETE FROM tb_dish WHERE dish_id = #{dishId}
    </delete>
</mapper>

  • DishCategoryMapper 接口与 XML 文件:类似地创建 SysDishCategoryMapper 接口和对应的 XML 文件,用于处理菜品分类的数据库操作。

3. 服务层开发

  • DishService 接口:在 ruoyi-admin/src/main/java/com/ruoyi/system/service 目录下创建 ISysDishService 接口。

java

package com.ruoyi.system.service;

import com.ruoyi.system.domain.SysDish;

import java.util.List;

public interface ISysDishService {
    List<SysDish> selectDishList(SysDish dish);
    int insertDish(SysDish dish);
    int updateDish(SysDish dish);
    int deleteDishById(Long dishId);
}

  • DishServiceImpl 实现类:在该目录下创建 SysDishServiceImpl 类。

java

package com.ruoyi.system.service.impl;

import com.ruoyi.system.domain.SysDish;
import com.ruoyi.system.mapper.SysDishMapper;
import com.ruoyi.system.service.ISysDishService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SysDishServiceImpl implements ISysDishService {
    @Autowired
    private SysDishMapper dishMapper;

    @Override
    public List<SysDish> selectDishList(SysDish dish) {
        return dishMapper.selectDishList(dish);
    }

    @Override
    public int insertDish(SysDish dish) {
        return dishMapper.insertDish(dish);
    }

    @Override
    public int updateDish(SysDish dish) {
        return dishMapper.updateDish(dish);
    }

    @Override
    public int deleteDishById(Long dishId) {
        return dishMapper.deleteDishById(dishId);
    }
}

4. 控制器开发

在 ruoyi-admin/src/main/java/com/ruoyi/system/controller 目录下创建 SysDishController 控制器。

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.SysDish;
import com.ruoyi.system.service.ISysDishService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/system/dish")
public class SysDishController extends BaseController {
    @Autowired
    private ISysDishService dishService;

    @GetMapping("/list")
    public TableDataInfo list(SysDish dish) {
        startPage();
        List<SysDish> list = dishService.selectDishList(dish);
        return getDataTable(list);
    }

    @PostMapping
    public AjaxResult add(@RequestBody SysDish dish) {
        return toAjax(dishService.insertDish(dish));
    }

    @PutMapping
    public AjaxResult edit(@RequestBody SysDish dish) {
        return toAjax(dishService.updateDish(dish));
    }

    @DeleteMapping("/{dishId}")
    public AjaxResult remove(@PathVariable Long dishId) {
        return toAjax(dishService.deleteDishById(dishId));
    }
}

四、前端开发

1. API 接口封装

在 ruoyi-ui/src/api/system 目录下创建 dish.js 文件。

javascript

import request from '@/utils/request'

export function getDishList(query) {
    return request({
        url: '/system/dish/list',
        method: 'get',
        params: query
    })
}

export function addDish(data) {
    return request({
        url: '/system/dish',
        method: 'post',
        data: data
    })
}

export function updateDish(data) {
    return request({
        url: '/system/dish',
        method: 'put',
        data: data
    })
}

export function deleteDish(dishId) {
    return request({
        url: `/system/dish/${dishId}`,
        method: 'delete'
    })
}

2. 页面组件开发

在 ruoyi-ui/src/views/system 目录下创建 dish 文件夹,并在其中创建 index.vue 文件。

vue

<template>
    <div>
        <el-form :inline="true" :model="queryParams" class="demo-form-inline">
            <el-form-item label="菜品名称">
                <el-input v-model="queryParams.dishName" placeholder="请输入菜品名称"></el-input>
            </el-form-item>
            <el-form-item label="菜品分类">
                <el-select v-model="queryParams.categoryId" placeholder="请选择分类">
                    <!-- 这里应动态加载分类数据 -->
                    <el-option label="分类 1" value="1"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" @click="getDishList">查询</el-button>
            </el-form-item>
        </el-form>
        <el-table :data="dishList" stripe>
            <el-table-column prop="dishId" label="菜品 ID"></el-table-column>
            <el-table-column prop="dishName" label="菜品名称"></el-table-column>
            <el-table-column prop="price" label="菜品价格"></el-table-column>
            <el-table-column label="菜品图片">
                <template slot-scope="scope">
                    <img :src="scope.row.imageUrl" alt="菜品图片" width="50">
                </template>
            </el-table-column>
            <el-table-column label="操作">
                <template slot-scope="scope">
                    <el-button type="primary" size="mini" @click="editDish(scope.row)">编辑</el-button>
                    <el-button type="danger" size="mini" @click="deleteDish(scope.row.dishId)">删除</el-button>
                </template>
            </el-table-column>
        </el-table>
        <el-dialog :visible.sync="dialogVisible" title="菜品信息">
            <el-form :model="dishForm">
                <el-form-item label="菜品名称">
                    <el-input v-model="dishForm.dishName"></el-input>
                </el-form-item>
                <el-form-item label="菜品价格">
                    <el-input v-model="dishForm.price"></el-input>
                </el-form-item>
                <el-form-item label="菜品分类">
                    <el-select v-model="dishForm.categoryId" placeholder="请选择分类">
                        <!-- 这里应动态加载分类数据 -->
                        <el-option label="分类 1" value="1"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="菜品图片">
                    <el-upload
                            action="#"
                            :show-file-list="false"
                            @success="handleUploadSuccess">
                        <el-button size="small" type="primary">上传图片</el-button>
                    </el-upload>
                    <img v-if="dishForm.imageUrl" :src="dishForm.imageUrl" alt="菜品图片" width="100">
                </el-form-item>
                <el-form-item label="菜品描述">
                    <el-input type="textarea" v-model="dishForm.description"></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="saveDish">保存</el-button>
            </div>
        </el-dialog>
    </div>
</template>

<script>
import { getDishList, addDish, updateDish, deleteDish } from '@/api/system/dish'

export default {
    data() {
        return {
            queryParams: {
                dishName: '',
                categoryId: null
            },
            dishList: [],
            dialogVisible: false,
            dishForm: {}
        }
    },
    created() {
        this.getDishList()
    },
    methods: {
        getDishList() {
            getDishList(this.queryParams).then(response => {
                this.dishList = response.rows
            })
        },
        editDish(row) {
            this.dishForm = { ...row }
            this.dialogVisible = true
        },
        saveDish() {
            if (this.dishForm.dishId) {
                updateDish(this.dishForm).then(response => {
                    if (response.code === 200) {
                        this.$message.success('更新成功')
                        this.dialogVisible = false
                        this.getDishList()
                    }
                })
            } else {
                addDish(this.dishForm).then(response => {
                    if (response.code === 200) {
                        this.$message.success('添加成功')
                        this.dialogVisible = false
                        this.getDishList()
                    }
                })
            }
        },
        deleteDish(dishId) {
            this.$confirm('确定要删除该菜品吗?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                deleteDish(dishId).then(response => {
                    if (response.code === 200) {
                        this.$message.success('删除成功')
                        this.getDishList()
                    }
                })
            })
        },
        handleUploadSuccess(response, file, fileList) {
            // 处理图片上传成功后的逻辑,更新 dishForm.imageUrl
            this.dishForm.imageUrl = response.data.url
        }
    }
}
</script>

3. 路由配置

在 ruoyi-ui/src/router/index.js 文件中添加菜品管理页面的路由配置。

javascript

{
    path: '/system/dish',
    component: Layout,
    children: [
        {
            path: 'index',
            name: 'DishManagement',
            component: () => import('@/views/system/dish/index'),
            meta: { title: '菜品管理', icon: 'table' }
        }
    ]
}

五、权限配置与测试

1. 权限配置

在系统管理 - 菜单管理中添加 “菜品管理” 菜单,设置相应的菜单信息,并关联到需要访问该模块的角色。同时,在 SysDishController 控制器的方法上添加权限注解,如 @PreAuthorize("@ss.hasPermi('system:dish:list')") 等。

2. 测试

启动若依后端和前端项目,使用具有相应权限的账号登录系统,测试菜品管理模块的各项功能,包括列表展示、添加、编辑、删除和查询等操作,确保功能正常且数据交互准确。

六、总结

通过本次二次开发,成功实现了若依框架下的菜品管理模块。在开发过程中,充分利用了若依框架的前后端结构和工具,遵循了数据库设计、实体类创建、Mapper 开发、服务层和控制器编写等后端开发流程,以及 API 封装、页面组件开发和路由配置等前端开发流程。同时,进行了权限配置,保证了系统的安全性和数据的访问控制。后续可以进一步优化该模块,如完善图片上传功能、优化界面样式等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值