第3章 从0开始用若依

一、项目开篇:为什么要基于若依框架开发项目

为什么要基于若依框架开发?

  1. 快速开发:若依框架提供了许多现成的模块和工具 ,能够快速搭建起一个基本的应用框架 ,从而减少了开发的时间和工作量

  2. 高度可定制性:若依框架提供了丰富的插件和扩展点,可以根据项目的需求进行定制和扩展,满足不同项目的特定需求。

  3. 简化开发流程:若依框架提供了许多常用的功能模块 ,如权限管理、数据字典、定时任务等,能够简化开发流程提高开发效率

  4. 易于维护和管理:若依框架采用了模块化的设计,代码结构清晰,易于维护和管理,有助于降低项目的维护成本。

  5. 社区支持和更新迭代:若依框架有一个活跃的开发社区,能够及时提供技术支持和更新迭代,保证项目的稳定性和安全性。

  6. 已毕业学员的强烈需要

本章的主题就是完成基于若依框架的前后端项目开发环境的搭建 ,熟悉若依框架前后端代码的结构 并进行简单的二次开发。

二、若依框架简介和若依框架中的版本选择

1、基本介绍

若依(RuoYi)框架是一款基于Spring Boot、Spring Cloud等开源框架搭建的企业级开发平台 。它的主要目标是提供全面的解决方案 ,以简化企业级应用开发提高开发效率。以下是对若依框架的详细介绍:

  1. 模块化设计 :若依框架采用模块化的设计,使得应用可以根据需求进行灵活的扩展和定制。每个模块都可以独立部署和升级,这大大提高了系统的可维护性和可扩展性。

  2. 前后端分离:框架采用前后端分离的开发模式,后端专注于数据处理和API接口的提供,前端则负责页面的展示和用户交互。这种模式使得前后端职责明确,进一步提高了开发效率和代码的可维护性。

  3. 权限管理 :若依框架提供了完善的用户权限管理功能 ,包括角色管理、菜单授权、部门管理等,便于对系统权限进行灵活的配置和管理

  4. 代码生成器 :框架内置代码生成器,能够快速生成前后端代码 ,减少重复劳动,提高开发效率。通过简单的配置即可生成基础的增删改查代码

  5. 定时任务 :若依框架集成了定时任务模块 ,支持动态添加定时任务, 可以通过界面对定时任务进行管理与调度。此外,框架还能实时查看系统运行日志和在线用户信息,监控服务状态和性能。

  6. 易于集成 :若依框架可以轻松地与其他常用技术栈集成,如MySQL、Redis、消息队列等。这使得开发者可以根据项目需求灵活地选择合适的技术组件,降低技术门槛和成本。

此外,若依框架还集成了许多常用功能模块,如文件上传下载、消息推送、数据字典、日志管理等。

总的来说,若依框架是一款功能丰富、易于扩展和定制的企业级开发平台,适用于各种Web应用程序的开发。它能够帮助开发者快速构建功能完备的应用,提高开发效率,降低维护成本。

若依官网地址:RuoYi 若依官方网站 |后台管理系统|权限管理系统|快速开发框架|企业管理系统|开源框架|微服务框架|前后端分离框架|开源后台系统|RuoYi|RuoYi-Vue|RuoYi-Cloud|RuoYi框架|RuoYi开源|RuoYi视频|若依视频|RuoYi开发文档|若依开发文档|Java开源框架|Java|SpringBoot|SrpingBoot2.0|SrpingCloud|Alibaba|MyBatis|Shiro|OAuth2.0|Thymeleaf|BootStrap|Vue|Element-UI||www.ruoyi.vip

若依框架分为四个版本:

  • 前后端不分离版本RuoYi(单体)

  • 前后端分离版RuoYi-Vue(单体)本项目使用版本

  • 微服务版本RuoYi-Cloud

  • 移动端版RuoYi-App

前三个版本都提供了前后端的项目,移动端版本可以适配RuoYi-Vue和RuoYi-Cloud的后端项目

2、RuoYi-Vue前后端分离版

咱们课程中重点讲解的是RuoYi-Vue前后端分离版本,

文档地址:介绍 | RuoYi

(1)概述

RuoYi-Vue 是一个 JavaEE 企业级快速开发平台,基于经典技术组合(SpringBoot、SpringSecurity、MyBatis、Jwt、Vue),

内置模块有:部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理、代码生成等。

在线定时任务配置;支持集群,支持多数据源,支持分布式事务。

演示地址:若依管理系统

(2)技术选型

1、系统环境

  • Java EE 8 ---> jdk 11

  • Servlet 3.0

  • Apache Maven 3

2、主框架

  • Spring Boot 2.5.x

  • Spring Framework 5.2.x

  • Spring Security 5.2.x 安全框架

3、持久层

  • Apache MyBatis 3.5.x ---> MyBatis Plus

  • Hibernate Validation 6.0.x 校验框架

  • Alibaba Druid 1.2.x

4、视图层

  • Vue 2.6.x ----> Vue3

  • Axios 0.21.x

  • Element 2.15.x ----> Element Plus

三、环境搭建

熟悉了若依的基本情况之后,下面,咱们就快速上手,来把这个框架搭建起来,并且需要顺利跑起来

1、准备工作

基础软件准备

官方推荐 优化升级
JDK >= 1.8 (推荐1.8版本) 升级为JDK 11 资料中提供了安装包
Maven >= 3.0 不需要安装,直接使用IDEA中自带的Maven即可
Node >= 12 前端代码由vue2升级为vue3,需要Node 18及以上的版本
Mysql >= 5.7.0 (推荐5.7版本) 升级为MySQL 8
Redis >= 3.0 本地启动

一般企业中服务器都是部署了一些项目中公用的基础环境,比如MySQL、Redis等这些。这些服务都是部署在linux服务器中,这些服务可能是部署在公司的一个机房 中,也有可能是云服务器(中小企业居多)。

在咱们教学的过程中,为了还原更真实的企业环境,咱们可以在VMWare软件中来部署linux服务器,当做咱们开发中的公用服务器 ,具体的VMWare服务配置请参考如下链接:虚拟机环境说明

在目前提供的虚拟机环境中已经使用docker安装了对应的基础环境,docker ps查看

详细说明如下:

软件名称 说明
MySQL 默认用户名:root,默认密码:heima123,端口:3306
Redis 默认密码:123456,端口:6379

运行中州养老项目,需要使用到MySQL和Redis,因此,这两个服务已经设置了开机自启,后面咱们的课程中会详细讲解和使用Redis

2、虚拟机环境说明

(1)挂载虚拟机

找到资料中的虚拟机镜像文件夹,解压后双击 CentOS 7 64位.vmx即可挂载到虚拟机中(需提前安装好VMWare)

编辑虚拟机-CD/DVD选择03虚拟机镜像中文件

网络适配器VMnet8(NAT模式)

双击后,在弹出的对话框中选择:我已移动此虚拟机,不让ip+1

(2)设置虚拟网络

因为此虚拟机已设置静态的ip地址,项目一采用的网段是192.168.100.0,所以为了减少环境网络的配置,可以手动设置虚拟机中NAT网卡的网段

设置步骤:

①:找到虚拟机的编辑按钮,打开虚拟网络编辑器

②:选中NAT模式的网卡,在下面的子网IP的输入框中手动 设置为:192.168.100.0,确定保存即可

DHCP设置也要改成192.168.100.128、192.168.100.254

③:右键虚拟机-->设置-->网络适配器-->自定义:选择Vmnet8(NAT模式)

④:启动服务器(网络设置完成后再启动服务器)

(2)FinalShell客户端链接

此虚拟机的静态ip为:192.168.100.168,防火墙已关闭,可以直接使用客户端连接

以FinalSehll工具为例:

注意:此虚拟机的用户名:root,密码:1234

2、运行后端项目

(1)下载代码

由于若依提供的代码的包名和项目名和咱们的需求不一致,因此这里暂时不要采用Git克隆的方式下载代码,直接下载ZIP包到本地,然后先替换所有的包名和项目名,再使用IDEA打开项目

注意注意:同学你好,为了避免若依官方代码更新后和后续课程中出现不一致的情况,这里强烈建议不要从gitee上拉取代码,直接使用课程资料中提供的后端初始代码:RuoYi-Vue-master.zip,和前端初始代码:RuoYi-Vue3-master.zip。这样就能确保初始代码环境和后续课程中保持一致,避免出现各种版本兼容的问题。

(2)包名全局替换

  • 从官方下载的代码中所有包名都为com.rouyi,且数据库连接信息需要修改,此时,咱们可以借助若依框架修改器来一键修改:

  • 参考链接:RuoYi-MT 发行版 - Gitee.com

  • 可以使用资料中提供的若依框架修改器

请参考下方截图进行修改哦

  • 修改完成之后,修改器会自动导出一个新的目录,将目录复制到你的代码目录中,然后使用idea打开即可:

打开项目后,先修改项目和模块使用的JDK版本为11。

  • 修改pom.xml文件中JDK的版本为11

(3)maven配置

打开之后,需要配置maven的本地仓库,由于pom文件中引入的依赖较多,如果你的网络不稳定,建议将资料中的本地仓库先解压到自己的Maven仓库中

idea中的配置

  • 修改idea中的项目编码为utf-8

(4)数据库准备和配置

  • 数据库使用的MySQL 8

    • 默认的用户名:root

    • 默认的密码:heima123

在idea中创建数据库并导入项目中的基础表结构和数据

  • 创建数据库 zzyl,可以打开项目根目录下的sql/ry_2025xxxx.sql文件:

打开这个文件,在最上方添加以下内容:

sql 复制代码
create database if not exists zzyl;
use zzyl;
  • 导入修改后的的sql/ry_2025xxxx.sql文件

sql执行成功以后,修改数据库连接,找到zzyl-admin模块中的resources目录下的application-druid.yml

TypeScript 复制代码
# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://192.168.100.168:3306/zzyl?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: root
                password: heima123

(5)Redis配置

找到ruoyi-admin模块中的resources目录下的application.yml,如下配置:

TypeScript 复制代码
# Spring配置
spring:
  redis:
    # 地址
    host: 192.168.100.168
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 0
    # 密码
    password: 123456
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms

(6)运行项目

找到ruoyi-admin模块中的运行com.ruoyi.RuoYiApplication.java,出现如下图表示启动成功。

html 复制代码
(♥◠‿◠)ノ゙  若依启动成功   ლ(´ڡ`ლ)゙  
 .-------.       ____     __        
 |  _ _   \      \   \   /  /    
 | ( ' )  |       \  _. /  '       
 |(_ o _) /        _( )_ .'         
 | (_,_).' __  ___(_ o _)'          
 |  |\ \  |  ||   |(_,_)'         
 |  | \ `'   /|   `-'  /           
 |  |  \    /  \      /           
 ''-'   `'-'    `-..-'              

3、将后端代码上传到Gitee

项目运行起来后,要将代码托管到gitee仓库中,方便维护。

先将当前的master分支上传到gitee ,然后在master分支上创建一个develop分支

将来,每一章的业务开发都要在develop分支上创建出一个子分支,子分支的命名规则为:dev+章数,例如本章的子分支为dev03,下一章的为dev04,依此类推。

每一章的代码在子分支测试完毕后,要合并到develop分支,下一章再从develop分支创建出一个新的分支。

4、运行前端项目

(1)前提

咱们要运行的前端项目,使用的是vue3,需要使用node 18版本以上

如果没有安装node18或者更高版本的同学,可以在资料中找到对应的安装包进行安装

(2)代码下载

目前下载的代码中,其中ruoyi-ui这个目录就是前端的代码,不过这个代码是基于vue2开发的

如果需要使用vue2为基础开发语言的前端,就可以使用上述的代码,运行方式跟下方描述相同

咱们需要使用基于vue3开发的代码,官方推荐的地址:GitHub - yangzongzhuan/RuoYi-Vue3: :tada: (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统 · GitHub

由于从github下载代码速度比较慢,已经将当前代码同步了一份到gitee中,地址如下:https://gitee.com/alexisyang/ruo-yi-vue3-master.git

也可以在本章的资料中找到代码压缩包,解压到代码目录,解压后,建议修改一下项目名(如:zzyl-vue3),再使用VSCode打开

注意注意:同学你好,为了避免若依官方代码更新后和后续课程中出现不一致的情况,这里强烈建议直接使用资料中提供的前端初始代码:RuoYi-Vue3-master.zip,这样就能确保初始代码环境和后续课程中保持一致啦

(3)安装依赖和项目运行

进入到代码的根目录,然后执行以下命令:

XML 复制代码
npm install

(4)修改配置

打开前端根目录下的vite.config.js文件,把目标地址改为若依后端的服务地址,如下图:

前端默认端口是80,由于Windows10操作系统上的80端口会被系统进程占用,最好提前修改好端口,再启动前端项目:

复制代码
  
javascript 复制代码
  // vite 相关配置
    server: {
      port: 88,
      host: true,
      open: true,
      proxy: {
        // https://cn.vitejs.dev/config/#server-proxy
        '/dev-api': {
          target: baseUrl,
          changeOrigin: true,
          rewrite: (p) => p.replace(/^\/dev-api/, '')
        },
         // springdoc proxy
         '^/v3/api-docs/(.*)': {
          target: baseUrl,
          changeOrigin: true,
        }
      }
    },

(5)启动项目

如果依赖已经安装完成,配置也已修改,则可以直接启动项目

javascript 复制代码
npm run dev

启动成功之后的效果:

html 复制代码
D:\ZZYL\Code\zzyl-vue3>npm run dev
​
> ruoyi@3.8.9 dev
> vite
​
​
  VITE v5.3.2  ready in 675 ms
​
  ➜  Local:   http://localhost:88/
  ➜  Network: http://172.16.17.61:88/
  ➜  Network: http://192.168.138.1:88/
  ➜  Network: http://192.168.100.1:88/
  ➜  press h + enter to show help

启动前后端成功后,会自动打开浏览器访问页面,地址:http://localhost:88/

5、将前端代码上传到Gitee

项目运行起来后,要将代码托管到gitee仓库中,方便维护。

先将当前的master分支上传到gitee,然后在master分支上创建一个develop分支;

将来,每一章的业务开发都要在develop分支上创建出一个子分支,子分支的命名规则为:dev+章数,例如本章的子分支为dev03,下一章的为dev04,依此类推。

每一章的代码在子分支测试完毕后,要合并到develop分支,下一章再从develop分支创建出一个新的分支。

四、后端代码

1、项目结构

下面是idea打开项目后的截图

官方文档的介绍

java 复制代码
com.ruoyi 

├── ruoyi-admin       // 后台服务   存放 controller    

├── common            // 工具类
│       └── annotation// 自定义注解
│       └── config	  // 全局配置
│       └── constant  // 通用常量
│       └── core      // 核心控制
│       └── enums     // 通用枚举
│       └── exception // 通用异常
│       └── filter    // 过滤器处理
│       └── utils     // 通用类处理

├── framework         // 框架核心
│       └── aspectj   // 注解实现
│       └── config    // 系统配置
│       └── datasource// 数据权限
│       └── interceptor// 拦截器
│       └── manager   // 异步处理
│       └── security  // 权限控制
│       └── web       // 前端控制

├── ruoyi-generator   // 代码生成(可移除)

├── ruoyi-quartz      // 定时任务(可移除)

├── ruoyi-system      // 系统代码   存放 domain,mapper,service

├── ruoyi-xxxxxx      // 其他模块

模块间的依赖关系

2、项目的配置

项目中的配置文件都在ruoyi-admin模块下,如下图:

  • i18n:国际化处理

  • META-INF:存储了项目的元信息(描述数据的数据),无需修改

  • mybatis:mybatis相关的配置信息

  • application.yml:项目中的核心配置

  • application-druid.yml:数据库连接配置

  • banner.txt:默认的banner图标信息,项目启动,控制台打印显示

  • logback.xml:日志配置

最主要的两个配置文件:application.yml和application-druid.yml

  • application.yml
TypeScript 复制代码
# 项目相关配置
ruoyi:
  # 名称
  name: RuoYi
  # 版本
  version: 3.8.9
  # 版权年份
  copyrightYear: 2025
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # 获取ip地址开关
  addressEnabled: false
  # 验证码类型 math 数字计算 char 字符验证
  captchaType: math

# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8080
  servlet:
    # 应用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # 连接数满后的排队数,默认为100
    accept-count: 1000
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100

# 日志配置
logging:
  level:
    com.zzyl: debug
    org.springframework: warn

# 用户配置
user:
  password:
    # 密码最大错误次数
    maxRetryCount: 5
    # 密码锁定时间(默认10分钟)
    lockTime: 10

# Spring配置
spring:
  # 资源信息
  messages:
    # 国际化资源文件路径
    basename: i18n/messages
  profiles:
    active: druid
  # 文件上传
  servlet:
    multipart:
      # 单个文件大小
      max-file-size: 10MB
      # 设置总上传的文件大小
      max-request-size: 20MB
  # 服务模块
  devtools:
    restart:
      # 热部署开关
      enabled: true
  # redis 配置
  redis:
    # 地址
    host: 192.168.100.168
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 0
    # 密码
    password: 123456
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms

# token配置
token:
  # 令牌自定义标识
  header: Authorization
  # 令牌密钥
  secret: abcdefghijklmnopqrstuvwxyz
  # 令牌有效期(默认30分钟)
  expireTime: 30

# MyBatis配置
mybatis:
  # 搜索指定包别名
  typeAliasesPackage: com.zzyl.**.domain
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # 加载全局的配置文件
  configLocation: classpath:mybatis/mybatis-config.xml

# PageHelper分页插件
pagehelper:
  helperDialect: mysql
  supportMethodsArguments: true
  params: count=countSql

# Swagger配置
swagger:
  # 是否开启swagger
  enabled: true
  # 请求前缀
  pathMapping: /dev-api

# 防止XSS攻击
xss:
  # 过滤开关
  enabled: true
  # 排除链接(多个用逗号分隔)
  excludes: /system/notice
  # 匹配链接
  urlPatterns: /system/*,/monitor/*,/tool/*
  • application-druid.yml
TypeScript 复制代码
# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://192.168.100.168:3306/zzyl?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: root
                password: heima123
            # 从库数据源
            slave:
                # 从数据源开关/默认关闭
                enabled: false
                url: 
                username: 
                password: 
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置连接超时时间
            connectTimeout: 30000
            # 配置网络超时时间
            socketTimeout: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置检测连接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter: 
                enabled: true
            statViewServlet:
                enabled: true
                # 设置白名单,不填则允许所有访问
                allow:
                url-pattern: /druid/*
                # 控制台管理用户名和密码
                login-username: ruoyi
                login-password: 123456
            filter:
                stat:
                    enabled: true
                    # 慢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true

3、项目的表结构

刚才咱们已经导入了关于若依的表结构,若依中默认提供了19张表,咱们可以先简单熟悉一下每个表代表的含义:

表结构说明及关系

表名 说明 关系
gen_table 代码生成业务表 代码生成
gen_table_column 代码生成业务表字段 代码生成
sys_config 参数配置表 数据字典
sys_dict_data 字典数据表 数据字典
sys_dict_type 字典类型表 数据字典
sys_job 定时任务调度表 定时任务
sys_job_log 定时任务调度日志表 定时任务
sys_logininfor 系统访问记录 日志
sys_oper_log 操作日志记录 日志
sys_notice 通知公告表
sys_menu 菜单表 权限
sys_dept 部门表 权限
sys_post 岗位信息表 权限
sys_role 角色信息表 权限
sys_role_dept 角色和部门关联表 权限
sys_role_menu 角色和菜单关联表 权限
sys_user 用户信息表 权限
sys_user_post 用户与岗位关联表 权限
sys_user_role 用户和角色关联表 权限

五、前端代码

1、项目结构

如下图:

详细目录或文件说明:

javascript 复制代码
├── bin                        // 执行脚本

├── public                     // 公共文件
│   ├── favicon.ico            // favicon图标

├── src                        // 源代码
│   ├── api                    // 所有请求,后台的api接口,开发时经常操作的目录
│   ├── assets                 // 主题 字体等静态资源
│   ├── components             // 全局公用组件
│   ├── directive              // 全局指令
│   ├── layout                 // 布局
│   ├── plugins                // 通用方法
│   ├── router                 // 路由
│   ├── store                  // 全局 store管理
│   ├── utils                  // 全局公用方法
│   ├── views                  // view,存储vue组件,开发时经常操作的目录
│   ├── App.vue                // 根组件
│   ├── main.js                // 入口 加载组件 初始化等
│   ├── permission.js          // 权限管理
│   └── settings.js            // 系统配置

├── vite                       // 前端构建工具

├── .env.development           // 开发环境配置

├── .env.production            // 生产环境配置

├── .env.staging               // 测试环境配置

├── .gitignore                 // git 忽略项

├── LICENSE                    // 许可证

├── package-lock.json          // 锁定项目依赖的具体版本号

├── package.json               // 配置项目的信息、名称、版本号、描述信息等

├── pnpm-lock.yaml             // 锁定项目依赖的具体版本号

└── vite.config.js             // 用于配置 Vue.js 项目的全局选项,可修改后台访问接口的路径

2、核心配置

在开发阶段,配置的修改是较少的,主要关于一个配置文件即可--->vite.config.js

java 复制代码
import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import createVitePlugins from './vite/plugins'

const baseUrl = 'http://localhost:8080' // 后端接口

// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
  const env = loadEnv(mode, process.cwd())
  const { VITE_APP_ENV } = env
  return {
    // 部署生产环境和开发环境下的URL。
    // 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
    // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
    base: VITE_APP_ENV === 'production' ? '/' : '/',
    plugins: createVitePlugins(env, command === 'build'),
    resolve: {
      // https://cn.vitejs.dev/config/#resolve-alias
      alias: {
        // 设置路径
        '~': path.resolve(__dirname, './'),
        // 设置别名
        '@': path.resolve(__dirname, './src')
      },
      // https://cn.vitejs.dev/config/#resolve-extensions
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
    },
    // 打包配置
    build: {
      // https://vite.dev/config/build-options.html
      sourcemap: command === 'build' ? false : 'inline',
      outDir: 'dist',
      assetsDir: 'assets',
      chunkSizeWarningLimit: 2000,
      rollupOptions: {
        output: {
          chunkFileNames: 'static/js/[name]-[hash].js',
          entryFileNames: 'static/js/[name]-[hash].js',
          assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
        }
      }
    },
    // vite 相关配置
    server: {
      port: 88,
      host: true,
      open: true,
      proxy: {
        // https://cn.vitejs.dev/config/#server-proxy
        '/dev-api': {
          target: baseUrl,
          changeOrigin: true,
          rewrite: (p) => p.replace(/^\/dev-api/, '')
        },
         // springdoc proxy
         '^/v3/api-docs/(.*)': {
          target: baseUrl,
          changeOrigin: true,
        }
      }
    },
    css: {
      postcss: {
        plugins: [
          {
            postcssPlugin: 'internal:charset-removal',
            AtRule: {
              charset: (atRule) => {
                if (atRule.name === 'charset') {
                  atRule.remove()
                }
              }
            }
          }
        ]
      }
    }
  }
})
  • 别名

    • ~ 代表 ./

    • @代表src目录

  • 前端服务端口---> port: 80,咱们已经修改为88了

  • 后端服务地址---> target: baseUrl

    • const baseUrl = '``http://localhost:8080``' // 后端接口
  • 路径重写---> rewrite: (p) => p.replace(/^\/dev-api/, '')

六、功能快速开发

熟悉了前后端项目的结构之后,接下来,咱们正式开始项目功能的开发

若依提供的代码生成功能 ,可以基于表结构快速生成前后端的代码,下面,咱们快速感受一下代码生成功能的强大吧

1、准备工作

咱们首先开发的是护理项目模块,咱们需要准备两部分内容,一个是一级菜单,第二个是表结构

(1)菜单

咱们要开发的模块是护理项目模块,而护理项目是子菜单,咱们需要先在若依项目中创建一个服务管理的一级菜单,方便对服务管理下的功能进行分类

最终的效果:

准备主菜单-->**服务管理,**详细配置,如下:

点击确定后,刷新页面,可以看到多了一个服务管理的一级菜单

(2)表结构

护理项目表结构定义如下:

sql 复制代码
CREATE TABLE `nursing_project` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '名称',
  `order_no` int DEFAULT NULL COMMENT '排序号',
  `unit` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '单位',
  `price` decimal(10,2) DEFAULT NULL COMMENT '价格',
  `image` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '图片',
  `nursing_requirement` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '护理要求',
  `status` int NOT NULL DEFAULT '1' COMMENT '状态(0:禁用,1:启用)',
  `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
  `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '更新人',
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=84 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='护理项目表';

执行以上sql,生成对应的数据库表

2、代码生成

(1)生成

找到系统工具 -->代码生成 ,然后点击导入按钮

选中nursing_project表结构,点击确定

在代码生成列表中,可以看到新增了一条数据

该数据对应了5个按钮

  • 预览生成后的代码

  • 修改代码生成的配置(常用)

  • 删除这条数据

  • 同步表结构(导入之后改动表的情况)

  • 下载离线代码包

(2)配置

在生成之前,咱们需要对代码生成做一些配置,咱们可以点击修改按钮,可以看到有三部分的配置

  • 基本信息

  • 字段信息

  • 生成信息

下图是**基本信息,**可以根据自己的需求修改:表、实体、表描述、作者相关的数据

下图是字段信息,详细描述如下图:

字段信息 描述
字段列名 表中的字段列名称
字段描述 字段的描述,自动读取建表语句中的comment信息,可根据实际情况更改
物理类型 数据库所对应的字段类型
Java类型 Java实体类中属性的类型,可改,例如,状态字段:Long类型可以修改为Integer
Java属性 Java实体类中所对应的属性名称
插入 新增的时候,需要插入的字段
编辑 修改的时候,需要插入的字段
列表 列表查询需要展示的字段
查询 列表查询,需要的条件字段
查询方式 与上面查询条件配合,选择对应的查询方式
必填 在插入和新增的时候,这个字段是否是必填项,可生成校验
显示类型 前端代码使用的组件类型,可根据实际情况选择
字典类型 字典管理是用来维护可枚举的数据的,如下拉框、单选按钮等,支持自定义

下图是**生成信息,**可以按照自己的实际情况,来修改包路径,模块名称,上级菜单

(3)提交

修改完成后,点击提交按钮

等咱们修改完毕后,回到了列表页,这个时候就可以点击下载按钮,去下载代码包

下载后的代码包,解压后,包含了三部分,如下图:

  • main 后端的代码

  • vue 前端的代码

  • projectMenu.sql 菜单关系的sql数据

执行projectMenu.sql文件中的内容,内容为菜单的数据

复制代码
-- 菜单 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('护理项目', '2000', '1', 'project', 'nursing/project/index', 1, 0, 'C', '0', '0', 'nursing:project:list', '#', 'admin', sysdate(), '', null, '护理项目菜单');

-- 按钮父菜单ID
SELECT @parentId := LAST_INSERT_ID();

-- 按钮 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('护理项目查询', @parentId, '1',  '#', '', 1, 0, 'F', '0', '0', 'nursing:project:query',        '#', 'admin', sysdate(), '', null, '');

insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('护理项目新增', @parentId, '2',  '#', '', 1, 0, 'F', '0', '0', 'nursing:project:add',          '#', 'admin', sysdate(), '', null, '');

insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('护理项目修改', @parentId, '3',  '#', '', 1, 0, 'F', '0', '0', 'nursing:project:edit',         '#', 'admin', sysdate(), '', null, '');

insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('护理项目删除', @parentId, '4',  '#', '', 1, 0, 'F', '0', '0', 'nursing:project:remove',       '#', 'admin', sysdate(), '', null, '');

insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('护理项目导出', @parentId, '5',  '#', '', 1, 0, 'F', '0', '0', 'nursing:project:export',       '#', 'admin', sysdate(), '', null, '');

把main目录拷贝后,找到后端ruoyi-admin模块,在main目录上点右键,选择Paste进行拷贝,效果如下:

打开vue文件夹,里面包含了两部分内容

  • api是指后端的接口定义代码

  • views中包含了vue组件的前端代码

选中这两个文件夹 ,打开前端项目,选中src目录进行拷贝,效果如下:

等代码拷贝完成后,重新启动前后端项目,打开页面,可以在服务管理 中看到子菜单护理项目,如下图

可以对护理项目进行一些操作,比如,新增、修改、删除、查询等

七、代码阅读

刚才自动生成的代码,不需要做任何修改,就可以做到基本的增删改查了,当然若依生成的代码也不是很完美,在后续的课程中,咱们还会进行修改调整。

在修改优化之前,咱们先来读一下自动生成的代码长什么样子,共分为两部分:后端和前端

1、后端代码

下面这个是控制层的代码NursingProjectController ,详细如下:

咱们可以使用AI协助来阅读以上代码,咱们可以让AI为每一行代码添加上注释,方便咱们阅读

(1)Prompt

咱们可以把整个类的代码给AI,然后在最后添加一句话: 帮我给方法上的注解和方法内的代码添加单行注释,注释要写在代码上方

AI解释后就可以很方便的阅读代码,详细如下:

java 复制代码
package com.zzyl.nursing.controller;

import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.zzyl.common.annotation.Log;
import com.zzyl.common.core.controller.BaseController;
import com.zzyl.common.core.domain.AjaxResult;
import com.zzyl.common.enums.BusinessType;
import com.zzyl.nursing.domain.NursingProject;
import com.zzyl.nursing.service.INursingProjectService;
import com.zzyl.common.utils.poi.ExcelUtil;
import com.zzyl.common.core.page.TableDataInfo;

/**
 * 护理项目Controller
 * 
 * @author ruoyi
 * @date 2025-05-16
 */
@RestController
@RequestMapping("/nursing/project")
public class NursingProjectController extends BaseController
{
    @Autowired
    private INursingProjectService nursingProjectService;

    /**
     * 查询护理项目列表
     */
    // 权限校验:需具备护理项目管理列表权限
    @PreAuthorize("@ss.hasPermi('nursing:project:list')")
    // 映射GET请求到/list路径
    @GetMapping("/list")
    public TableDataInfo list(NursingProject nursingProject)
    {
        // 开启分页功能
        startPage();
        // 调用服务层查询护理项目列表
        List<NursingProject> list = nursingProjectService.selectNursingProjectList(nursingProject);
        // 返回分页数据表格
        return getDataTable(list);
    }

    /**
     * 导出护理项目列表
     */
    // 权限校验:需具备护理项目管理导出权限
    @PreAuthorize("@ss.hasPermi('nursing:project:export')")
    // 记录操作日志:业务类型为导出
    @Log(title = "护理项目", businessType = BusinessType.EXPORT)
    // 映射POST请求到/export路径
    @PostMapping("/export")
    public void export(HttpServletResponse response, NursingProject nursingProject)
    {
        // 查询需要导出的护理项目数据
        List<NursingProject> list = nursingProjectService.selectNursingProjectList(nursingProject);
        // 创建Excel工具类实例
        ExcelUtil<NursingProject> util = new ExcelUtil<NursingProject>(NursingProject.class);
        // 执行Excel导出操作
        util.exportExcel(response, list, "护理项目数据");
    }

    /**
     * 获取护理项目详细信息
     */
    // 权限校验:需具备护理项目管理查询权限
    @PreAuthorize("@ss.hasPermi('nursing:project:query')")
    // 映射GET请求到/{id}路径
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        // 调用服务层根据ID查询护理项目详情
        return success(nursingProjectService.selectNursingProjectById(id));
    }

    /**
     * 新增护理项目
     */
    // 权限校验:需具备护理项目管理新增权限
    @PreAuthorize("@ss.hasPermi('nursing:project:add')")
    // 记录操作日志:业务类型为新增
    @Log(title = "护理项目", businessType = BusinessType.INSERT)
    // 映射POST请求到根路径
    @PostMapping
    public AjaxResult add(@RequestBody NursingProject nursingProject)
    {
        // 调用服务层插入护理项目数据
        return toAjax(nursingProjectService.insertNursingProject(nursingProject));
    }

    /**
     * 修改护理项目
     */
    @PreAuthorize("@ss.hasPermi('nursing:project:edit')")
    @Log(title = "护理项目", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody NursingProject nursingProject)
    {
        return toAjax(nursingProjectService.updateNursingProject(nursingProject));
    }

    /**
     * 删除护理项目
     */
    // 权限校验:需具备护理项目管理删除权限
    @PreAuthorize("@ss.hasPermi('nursing:project:remove')")
    // 记录操作日志:业务类型为删除
    @Log(title = "护理项目", businessType = BusinessType.DELETE)
    // 映射DELETE请求到/{ids}路径
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        // 调用服务层批量删除护理项目
        return toAjax(nursingProjectService.deleteNursingProjectByIds(ids));
    }
}

(2)说明

1、继承了BaseController,其中BaseController详细定义如下图:

2、符合RestFul请求风格

3、返回值有两个:TableDataInfo 和 AjaxResult

  • TableDataInfo 返回分页相关数据
java 复制代码
{
    "total": 2,
    "rows": [
        {
            "createBy": "admin",
            "createTime": "2025-03-25 21:29:45",
            "updateBy": "",
            "updateTime": null,
            "remark": "管理员",
            "noticeId": "2",
            "noticeTitle": "维护通知:2018-07-01 若依系统凌晨维护",
            "noticeType": "1",
            "noticeContent": "维护内容",
            "status": "0"
        }
    ],
    "code": 200,
    "msg": "查询成功"
}
  • AjaxResult 继承了HashMap,有标准的接口响应结构
java 复制代码
{"msg":"操作成功","code":200}


{
    "msg": "操作成功",
    "code": 200,
    "data": {
        "createBy": "admin",
        "createTime": "2025-03-25 21:29:45",
        "remark": "管理员",
        "noticeId": "1",
        "noticeTitle": "温馨提醒:2018-07-01 若依新版本发布啦",
        "noticeType": "2",
        "noticeContent": "新版本内容",
        "status": "0"
    }
}

4、陌生注解

  • @PreAuthorize 在方法上使用,主要作用是判断当前登录人是否有权限访问该方法 ps:后面会细讲

  • @Log在方法上使用,作用是把操作这个方法的行为做一个日志记录

5、后端其他代码

  1. 比如service、mapper,这些代码都是基础的CRUD,操作数据使用的mybatis

6、分页逻辑

  1. 详细分页逻辑如下图:

当调用了startPage()方法后主要干了两件事:

  1. 从请求参数中获取到pageNum和pageSize两个参数,如果有其他参数也会获取,比如是orderBy参数

  2. 调用了PageHelper.startPage()方法,来进行分页处理

2、前端代码

(1)菜单路由规则,映射关系

知识回顾:

路由:是路径与组件的对应关系 ,可以实现不同页面间导航和视图的切换

咱们来看一下目前护理项目这个菜单的配置项,如下图

  • 这个菜单的类型为菜单, 菜单需要有对应的组件路径

  • 父菜单的路由地址+当前菜单的路由地址 就可以访问组件路径对应的组件

    • 即: nursing/project 加载组件为 @/views/nursing/project/index.vue

(2)测试案例

在服务管理中新增一个菜单(护理安排),配置如下:

  • 路由地址:arrange

  • 组件路径:nursing/arrange/index

在@/views/nursing/arrange目录中新增一个index.vue组件

测试是否能正常访问这个组件

(3)代码阅读

刚才生成代码中包含了两部分内容,第一个是api,第二个是组件

咱们先来看@/api/nursing/project.js

javascript 复制代码
import request from '@/utils/request'

// 查询护理项目列表
export function listProject(query) {
  return request({
    url: '/nursing/project/list',
    method: 'get',
    params: query
  })
}

// 查询护理项目详细
export function getProject(id) {
  return request({
    url: '/nursing/project/' + id,
    method: 'get'
  })
}

// 新增护理项目
export function addProject(data) {
  return request({
    url: '/nursing/project',
    method: 'post',
    data: data
  })
}

// 修改护理项目
export function updateProject(data) {
  return request({
    url: '/nursing/project',
    method: 'put',
    data: data
  })
}

// 删除护理项目
export function delProject(id) {
  return request({
    url: '/nursing/project/' + id,
    method: 'delete'
  })
}
  • 这里面的5个接口定义,与后台提供的接口是一一对应的

  • 其中@/utils/request这个js封装了拦截器和工具函数,实现了对HTTP请求和响应的统一处理和管理

咱们接下来再来看一下组件的代码,地址:src\views\nursing\project\index.vue

为了更方便阅读这个代码,咱们依然可以使用通义灵码或者是AI大模型添加注释或者解释代码

Prompt

把这个组件的代码给大模型,然后跟上一句话

你是一个资深的前端开发工程师,帮我给这个文件中的核心代码加上注释

解释后的代码如下:

javascript 复制代码
<script setup name="Project">
import { listProject, getProject, delProject, addProject, updateProject } from "@/api/nursing/project"

// 获取当前组件实例
const { proxy } = getCurrentInstance()

// 数据列表
const projectList = ref([])
// 对话框开关
const open = ref(false)
// 加载状态
const loading = ref(true)
// 搜索区域显示状态
const showSearch = ref(true)
// 选中ID数组
const ids = ref([])
// 单条选择状态
const single = ref(true)
// 多条选择状态
const multiple = ref(true)
// 总记录数
const total = ref(0)
// 弹窗标题
const title = ref("")

// 响应式数据对象
const data = reactive({
  form: {}, // 表单数据
  queryParams: { // 查询参数
    pageNum: 1,
    pageSize: 10,
    name: null,
    status: null,
  },
  rules: {} // 表单验证规则
})

const { queryParams, form, rules } = toRefs(data)

/** 查询护理项目列表 */
function getList() {
  loading.value = true
  listProject(queryParams.value).then(response => {
    projectList.value = response.rows
    total.value = response.total
    loading.value = false
  })
}

// 取消按钮操作
function cancel() {
  open.value = false
  reset()
}

// 表单重置
function reset() {
  form.value = {
    id: null,
    name: null,
    orderNo: null,
    unit: null,
    price: null,
    image: null,
    nursingRequirement: null,
    status: null,
    createBy: null,
    updateBy: null,
    remark: null,
    createTime: null,
    updateTime: null
  }
  proxy.resetForm("projectRef")
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1
  getList()
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef")
  handleQuery()
}

// 多选框选中数据处理
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.id)
  single.value = selection.length != 1
  multiple.value = !selection.length
}

/** 新增按钮操作 */
function handleAdd() {
  reset()
  open.value = true
  title.value = "添加护理项目"
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset()
  const _id = row.id || ids.value
  getProject(_id).then(response => {
    form.value = response.data
    open.value = true
    title.value = "修改护理项目"
  })
}

/** 提交按钮操作 */
function submitForm() {
  proxy.$refs["projectRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateProject(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功")
          open.value = false
          getList()
        })
      } else {
        addProject(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功")
          open.value = false
          getList()
        })
      }
    }
  })
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value
  proxy.$modal.confirm('是否确认删除护理项目编号为"' + _ids + '"的数据项?').then(function() {
    return delProject(_ids)
  }).then(() => {
    getList()
    proxy.$modal.msgSuccess("删除成功")
  }).catch(() => {})
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download('nursing/project/export', {
    ...queryParams.value
  }, `project_${new Date().getTime()}.xlsx`)
}

// 页面加载时获取数据
getList()
</script>
  • 前端主要使用Vue3+Element plus组件进行开发

八、将业务代码迁移到新模块

在前面的功能快速开发章节中,咱们是将若依生成的功能代码直接放到了zzyl-admin模块中 ,将来,咱们的业务功能代码会越来越多,如果都放到zzyl-admin模块中,会让zzyl-admin模块显得比较乱。所以,咱们最好创建一个新模块 ,然后将功能模块的代码统一都放到新模块中。以下是具体的操作思路:

参考链接(在若依项目中创建新模块):

后台手册 | RuoYi

要求:

  • 创建zzyl-nursing-platform模块,效果如下:
  • 在父模块中管理zzyl-nursing-platform模块的版本:
XML 复制代码
<!-- 业务模块-->
<dependency>
    <groupId>com.zzyl</groupId>
    <artifactId>zzyl-nursing-platform</artifactId>
    <version>${zzyl.version}</version>
</dependency>
  • 在zzyl-nursing-platform模块中引入zzyl-common模块
XML 复制代码
<dependencies>
    <dependency>
        <groupId>com.zzyl</groupId>
        <artifactId>zzyl-common</artifactId>
    </dependency>
</dependencies>
  • 在zzyl-admin模块中引入新创建的zzyl-nursing-platform模块
XML 复制代码
<!-- 护理业务模块-->
<dependency>
    <groupId>com.zzyl</groupId>
    <artifactId>zzyl-nursing-platform</artifactId>
</dependency>
  • 护理项目相关的代码,都移动到新模块中 zzyl-nursing-platform

    • 统一修改包名为com.zzyl.nursing

修改完成后,重启后端程序,完成测试。

九、微实战

1、需求说明

服务管理->护理计划包含:护理项目、护理计划、护理等级共3个子模块。

  • 护理项目 作为护理模块的基础数据,主要是由护理员给老人提供的护理服务,常见的有:洗头、助餐、复健运动等,护理项目分为护理计划内项目护理计划外项目,两者之间的区别是:前者是根据护理计划产生的,后者是由家属从微信小程序端下单支付产生的

  • 护理计划 作为护理模块的基础数据,主要是与护理等级和护理项目进行绑定 ,后台管理人员在创建计划时,可选择该计划要执行哪些任护理项目;后台管理人员可以对护理计划进行增删改等操作

  • 护理等级作为护理模块的基础数据,主要是与护理计划进行一对一的绑定,老人入住养老院时需要选择适合老人身体健康状况的护理等级,不同的护理等级对应的护理计划不同,不同护理计划绑定的护理项目不同,因此,价格也有区别

  • 三者关系

2、表结构

sql 复制代码
use zzyl;
-- 护理项目与护理计划关系表
CREATE TABLE nursing_project_plan (
  id bigint NOT NULL AUTO_INCREMENT,
  plan_id bigint NOT NULL COMMENT '计划id',
  project_id bigint NOT NULL COMMENT '项目id',
  execute_time varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '计划执行时间',
  execute_cycle int NOT NULL COMMENT '执行周期 0 天 1 周 2月',
  execute_frequency int NOT NULL COMMENT '执行频次',
  create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间(新增自动更新配置)',
  create_by bigint DEFAULT NULL COMMENT '创建人id',
  update_by bigint DEFAULT NULL COMMENT '更新人id',
  remark varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (id) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1727 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='护理计划和项目关联表';

-- 护理计划表
CREATE TABLE nursing_plan (
  id bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
  sort_no int DEFAULT NULL COMMENT '排序号',
  plan_name varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '名称',
  status tinyint NOT NULL DEFAULT '0' COMMENT '状态 0禁用 1启用',
  create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  create_by bigint DEFAULT NULL COMMENT '创建人id',
  update_by bigint DEFAULT NULL COMMENT '更新人id',
  remark varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (id) USING BTREE,
  UNIQUE KEY plan_name (plan_name) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=129 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='护理计划表';

-- 护理等级表
CREATE TABLE nursing_level (
  id bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  name varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '等级名称',
  plan_id bigint NOT NULL COMMENT '护理计划ID',
  fee decimal(10,2) NOT NULL COMMENT '护理费用',
  status tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用,1:启用)',
  description varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '等级说明',
  remark varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '备注',
  create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  create_by bigint DEFAULT NULL COMMENT '创建人id',
  update_by bigint DEFAULT NULL COMMENT '更新人id',
  PRIMARY KEY (id) USING BTREE,
  UNIQUE KEY name (name) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=76 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='护理等级表';

3、实现要求

  1. 把所有业务代码的都存储在zzyl-nursing-platform模块下

  2. 请使用若依的代码快速生成的功能 ,完成护理计划和护理等级的功能开发,最终效果图

4、讲解

十、提交代码

相关推荐
Json____1 小时前
五金制品行业-企业官网源码
java·大数据·数据库·企业站·wwwoop.com
夜雪一千1 小时前
Python 如何实现 SHA 加密?SHA1 / SHA256 / SHA512 实战教程
开发语言·python
有点。2 小时前
C++二叉树(一)
开发语言·数据结构·c++
民乐团扒谱机2 小时前
【微实验】谐波乘积谱(HPS)算法深度解析:原理、数学与代码实现
开发语言·人工智能·python·算法·语音识别·音乐
报错小能手2 小时前
Go 语言结构 基础语法
开发语言·后端·golang
Lazionr2 小时前
stack与queue:底层实现与容器适配器
开发语言·数据结构·c++
剩下了什么2 小时前
go语言 Ctx:「错误三:在 Context 中存储可变值」
开发语言·后端·golang
Hello_Damon_Nikola2 小时前
CH573从入门到精通
c语言·开发语言·单片机·嵌入式硬件
Logintern093 小时前
Langgraph使用MemorySaver建立有记忆的图
开发语言·windows·python