ruoyi-vue-pro 开发指南 ruoyi-vue-pro 开发指南
      视频教程
        微服务版 (opens new window)
        作者博客 (opens new window)
        GitHub (opens new window)
        • 萌新必读

          • 简介
          • 交流群
          • 视频教程
          • 功能列表
          • 快速启动(后端项目)
          • 快速启动(前端项目)
          • 接口文档
          • 技术选型
          • 项目结构
          • 代码热加载
          • 一键改包
          • 删除功能
          • 内网穿透
          • 达梦数据库专属
        • 后端手册

          • 新建模块
          • 代码生成【单表】(新增功能)
          • 代码生成【主子表】
          • 代码生成(树表)
          • 功能权限
          • 数据权限
          • 用户体系
          • 三方登录
          • OAuth 2.0(SSO 单点登录)
          • SaaS 多租户【字段隔离】
          • SaaS 多租户【数据库隔离】
          • WebSocket 实时通信
          • 异常处理(错误码)
          • 参数校验、时间传参
          • 分页实现
          • VO 对象转换、数据翻译
          • 文件存储(上传下载)
          • Excel 导入导出
          • 操作日志、访问日志、异常日志
          • MyBatis 数据库
          • MyBatis 联表&分页查询
          • 多数据源(读写分离)、事务
          • Redis 缓存
          • 本地缓存
          • 异步任务
          • 分布式锁
          • 幂等性(防重复提交)
          • 请求限流(RateLimiter)
          • 单元测试
          • 验证码
          • 工具类 Util
          • 配置管理
          • 数据库文档
        • 中间件手册

          • 定时任务
          • 消息队列(内存)
          • 消息队列(Redis)
          • 消息队列(RocketMQ)
          • 消息队列(RabbitMQ)
          • 消息队列(Kafka)
          • 限流熔断
        • 工作流手册

          • 工作流演示
          • 功能开启
          • 工作流(达梦适配)
          • 审批接入(流程表单)
          • 审批接入(业务表单)
          • 流程设计器(BPMN)
          • 流程设计器(钉钉、飞书)
          • 选择审批人、发起人自选
          • 会签、或签、依次审批
          • 流程发起、取消、重新发起
          • 审批通过、不通过、驳回
          • 审批加签、减签
          • 审批转办、委派、抄送
          • 执行监听器、任务监听器
          • 流程表达式
          • 流程审批通知
        • 大屏手册

          • 报表设计器
          • 大屏设计器
        • 支付手册

          • 功能开启
          • 支付宝支付接入
          • 微信公众号支付接入
          • 微信小程序支付接入
          • 支付宝、微信退款接入
        • 会员手册

          • 功能开启
          • 微信公众号登录
          • 微信小程序登录
          • 会员用户、标签、分组
          • 会员等级、积分、签到
        • 商城手册

          • 商城演示
          • 功能开启
          • 商城装修
          • 【商品】商品分类
          • 【商品】商品属性
          • 【商品】商品 SPU 与 SKU
          • 【商品】商品评价
          • 【交易】购物车
          • 【交易】交易订单
          • 【交易】售后退款
          • 【交易】快递发货
          • 【交易】门店自提
          • 【交易】分销返佣
          • 【营销】优惠劵
          • 【营销】拼团活动
          • 【营销】秒杀活动
          • 【营销】砍价活动
          • 【营销】满减送
          • 【营销】限时折扣
          • 【营销】内容管理
          • 【统计】会员、商品、交易统计
        • ERP手册

          • ERP 演示
          • 功能开启
          • 【产品】产品信息、分类、单位
          • 【库存】产品库存、库存明细
          • 【库存】其它入库、其它出库
          • 【库存】库存调拨、库存盘点
          • 【采购】采购订单、入库、退货
          • 【销售】销售订单、出库、退货
          • 【财务】采购付款、销售收款
        • CRM手册

          • CRM 演示
          • 功能开启
          • 【线索】线索管理
          • 【客户】客户管理、公海客户
          • 【商机】商机管理、商机状态
          • 【合同】合同管理、合同提醒
          • 【回款】回款管理、回款计划
          • 【产品】产品管理、产品分类
          • 【通用】数据权限
          • 【通用】跟进记录、待办事项
        • 公众号手册

          • 功能开启
          • 公众号接入
          • 公众号粉丝
          • 公众号标签
          • 公众号消息
          • 自动回复
          • 公众号菜单
          • 公众号素材
          • 公众号图文
          • 公众号统计
        • 系统手册

          • 短信配置
          • 邮件配置
          • 站内信配置
          • 数据脱敏
          • 敏感词
          • 地区 & IP 库
        • 运维手册

          • 开发环境
          • Linux 部署
          • Docker 部署
          • Jenkins 部署
          • HTTPS 证书
          • 服务监控
        • 前端手册 Vue 3.x

          • 开发规范
          • 菜单路由
          • Icon 图标
          • 字典数据
          • 系统组件
          • 通用方法
          • 配置读取
          • CRUD 组件
          • 国际化
          • IDE 调试
          • 代码格式化
        • 前端手册 Vue 2.x

          • 开发规范
            • 菜单路由
            • Icon 图标
            • 字典数据
            • 系统组件
            • 通用方法
            • 配置读取
          • 更新日志

            • 【v2.1.0】开发中
            • 【v2.0.1】2024-03-01
            • 【v2.0.0】2024-01-26
            • 【v1.9.0】2023-12-01
            • 【v1.8.3】2023-10-24
          • 开发指南
          • 前端手册 Vue 2.x
          芋道源码
          2022-04-17
          目录
          1. view 页面
          2. api 请求
          2.1 请求封装
          2.2 交互流程
          2.3 自定义 baseURL 基础路径
          3. component 组件
          4. style 样式

          开发规范

          # 1. view 页面

          在 @views (opens new window) 目录下,每个模块对应一个目录,它的所有功能的 .vue 都放在该目录里。

           目录

          一般来说,一个路由对应一个 .vue 文件。

          # 2. api 请求

          在 @/api (opens new window) 目录下,每个模块对应一个 .api 文件。

           目录

          每个 API 方法,会调用 request 方法,发起对后端 RESTful API 的调用。

          # 2.1 请求封装

          @/utils/request (opens new window) 基于 axios (opens new window) 封装,统一处理 GET、POST 方法的请求参数、请求头,以及错误提示信息等。

          # 2.1.1 创建 axios 实例

          • baseURL 基础路径
          • timeout 超时时间
          实现代码
          import axios from 'axios'
          
          // 创建 axios 实例
          const service = axios.create({
              // axios 中请求配置有 baseURL 选项,表示请求 URL 公共部分
              baseURL: process.env.VUE_APP_BASE_API + '/admin-api/', // 此处的 /admin-api/ 地址,原因是后端的基础路径为 /admin-api/
              // 超时
              timeout: 10000
          })
          

          # 2.1.2 Request 拦截器

          • Authorization、tenant-id 请求头
          • GET 请求参数的拼接
          实现代码
          import { getToken } from '@/utils/auth'
          import { getTenantEnable } from "@/utils/ruoyi";
          import Cookies from "js-cookie";
          
          service.interceptors.request.use(config => {
              // 是否需要设置 token
              const isToken = (config.headers || {}).isToken === false
              if (getToken() && !isToken) {
                  config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
              }
              // 设置租户
              if (getTenantEnable()) {
                  const tenantId = Cookies.get('tenantId');
                  if (tenantId) {
                      config.headers['tenant-id'] = tenantId;
                  }
              }
              // get 请求映射 params 参数
              if (config.method === 'get' && config.params) {
                  let url = config.url + '?';
                  for (const propName of Object.keys(config.params)) {
                      const value = config.params[propName];
                      var part = encodeURIComponent(propName) + "=";
                      if (value !== null && typeof(value) !== "undefined") {
                          if (typeof value === 'object') {
                              for (const key of Object.keys(value)) {
                                  let params = propName + '[' + key + ']';
                                  var subPart = encodeURIComponent(params) + "=";
                                  url += subPart + encodeURIComponent(value[key]) + "&";
                              }
                          } else {
                              url += part + encodeURIComponent(value) + "&";
                          }
                      }
                  }
                  url = url.slice(0, -1);
                  config.params = {};
                  config.url = url;
              }
              return config
          }, error => {
              console.log(error)
              Promise.reject(error)
          })
          

          # 2.1.3 Response 拦截器

          • Token 失效、登录过期时,跳回首页
          • 请求失败,Message 错误提示
          实现代码
          import { Notification, MessageBox, Message } from 'element-ui'
          import store from '@/store'
          import errorCode from '@/utils/errorCode'
          import Cookies from "js-cookie";
          
          export let isRelogin = { show: false };
          
          service.interceptors.response.use(res => {
              // 未设置状态码则默认成功状态
              const code = res.data.code || 200;
              // 获取错误信息
              const msg = errorCode[code] || res.data.msg || errorCode['default']
              if (code === 401) {
                if (!isRelogin.show) {
                  isRelogin.show = true;
                  MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
                      confirmButtonText: '重新登录',
                      cancelButtonText: '取消',
                      type: 'warning'
                    }
                  ).then(() => {
                    isRelogin.show = false;
                    store.dispatch('LogOut').then(() => {
                      location.href = '/index';
                    })
                  }).catch(() => {
                    isRelogin.show = false;
                  });
                }
                return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
              } else if (code === 500) {
                Message({
                  message: msg,
                  type: 'error'
                })
                return Promise.reject(new Error(msg))
              } else if (code !== 200) {
                Notification.error({
                  title: msg
                })
                return Promise.reject('error')
              } else { // 请求成功!
                return res.data
              }
            },
            error => {
              console.log('err' + error)
              let { message } = error;
              if (message === "Network Error") {
                message = "后端接口连接异常";
              }
              else if (message.includes("timeout")) {
                message = "系统接口请求超时";
              }
              else if (message.includes("Request failed with status code")) {
                message = "系统接口" + message.substr(message.length - 3) + "异常";
              }
              Message({
                message: message,
                type: 'error',
                duration: 5 * 1000
              })
              return Promise.reject(error)
            }
          )
          

          # 2.2 交互流程

          一个完整的前端 UI 交互到服务端处理流程,如下图所示:

          交互流程

          以 [系统管理 -> 用户管理] 菜单为例,查看它是如何读取用户列表的。代码如下:

          // ① api/system/user.js
          import request from '@/utils/request'
          
          // 查询用户列表
          export function listUser(query) {
              return request({
                  url: '/system/user/page',
                  method: 'get',
                  params: query
              })
          }
          
          // ② views/system/user/index.vue
          import { listUser } from "@/api/system/user";
          
          export default {
            data() {
              userList: null,
              loading: true
            },
            methods: {
              getList() {
                this.loading = true
                listUser().then(response => {
                  this.userList = response.rows
                  this.loading = false
                })
              }
            }
          }
          

          # 2.3 自定义 baseURL 基础路径

          如果想要自定义的 baseURL 基础路径,可以通过 baseURL 进行直接覆盖。示例如下:

          export function listUser(query) {
              return request({
                  url: '/system/user/page',
                  method: 'get',
                  params: query,
                  baseURL: 'https://www.iocoder.cn' // 自定义
              })
          }
          

          # 3. component 组件

          ① 在 @/components (opens new window) 目录下,实现全局组件,被所有模块所公用。例如说,富文本编辑器、各种各搜索组件、封装的分页组件等等。

          全局组件

          ② 每个模块的业务组件,可实现在 views 目录下,自己模块的目录的 components 目录下,避免单个 .vue 文件过大,降低维护成功。例如说,@/views/pay/app/components/xxx.vue。

          业务组件

          # 4. style 样式

          ① 在 @/styles (opens new window) 目录下,实现全局样式,被所有页面所公用。

          全局样式

          ② 每个 .vue 页面,可在 <style /> 标签中添加样式,注意需要添加 scoped 表示只作用在当前页面里,避免造成全局的样式污染。

          业务样式

          代码格式化
          菜单路由

          ← 代码格式化 菜单路由→

          Theme by Vdoing | Copyright © 2019-2024 芋道源码 | MIT License
            ×