基于Midwayjs的管理系统-接口程序目录手册

3,468 阅读4分钟

基于Midwayjs的管理系统-接口程序目录手册

基于 MidwayJS 4.x + Koa + TypeORM 的管理系统后端接口服务,参考 RuoYi-Vue 重构。

项目结构

mask_api_midwayjs
├── assets                      静态资源(ip2region.xdb、Excel 模板)
├── docs                        项目文档
├── script                      部署脚本(Dockerfile、SQL、构建脚本)
├── src                         源代码
│   ├── assets                  运行时静态资源(构建时复制到 dist-ncc)
│   ├── config                  多环境运行配置
│   ├── framework               核心通用代码
│   ├── modules                 业务模块
│   ├── typings                 全局类型定义
│   ├── bootstrap-bin.ts        ncc 单文件打包入口
│   ├── configuration.ts        Midway 框架启动入口
│   └── index.ts                模块导出入口(bundle 命令自动生成)
├── test                        测试用例
├── bootstrap.js                PM2 部署启动入口
├── docker-compose.yaml         Docker 容器编排
├── eslint.config.js            ESLint 配置
├── jest.config.js              Jest 测试配置
├── package.json                依赖及启动命令
└── tsconfig.json               TypeScript 配置

assets

程序内置静态资源,通过 assetsPath() 函数统一读取,由 APP_ASSETS 环境变量指定目录路径。

import { assetsPath } from "../framework/utils/assets-path";

// 读取 IP 数据库
const dbPath = assetsPath("ip2region.xdb");

// 读取 Excel 模板
const tplPath = assetsPath("template/excel", "user_import_template.xlsx");
环境APP_ASSETS 值
开发模式./src/assets
ncc 构建./assets
测试模式自动回退 cwd/src/assets

详见 src/framework/utils/assets-path.tssrc/framework/utils/file/file.ts 中的 readAssetsFileStream 方法。

src/config

参考 Midway 官方-多环境配置

文件环境说明
config.default.ts全局默认基础配置
config.local.tslocal本地开发覆盖
config.unittest.tsunittest测试环境覆盖

一般只需修改本地开发(local)的配置文件,对默认(default)配置进行参数覆盖。生产环境通过 .env 文件注入。

src/framework

封装的核心通用代码,应用于整个程序。

framework
├── catch                   全局异常捕获
├── config                  配置工具
├── constants               常量定义
├── datasource              数据源封装(数据库 + Redis)
├── ip2region               IP 归属地查询
├── middleware               中间件
├── reqctx                  请求上下文
├── resp                    响应封装
├── token                   JWT 令牌处理
└── utils                   工具函数
    ├── assets-path.ts      资源路径解析
    ├── crypto              加密工具
    ├── date                日期工具
    ├── file                文件工具(上传、读取、Excel)
    ├── generate            生成工具(验证码、随机码)
    ├── parse               解析工具
    ├── regular             正则工具
    └── ua                  浏览器 UA 工具

catch — 全局异常捕获

统一拦截异常并格式化响应:

异常说明
ForbiddenError403 当前操作没有权限
UnauthorizedError401 未授权认证用户
NotFoundError404 页面未找到
validate_error422 参数校验失败
error_catch500 未知异常

datasource — 数据源封装

  • datasource/db/ — TypeORM 数据库连接,支持原生 SQL 执行
  • datasource/redis/ — Redis 缓存连接

ip2region — IP 归属地

根据 IP 地址查询归属地信息,数据文件为 assets/ip2region.xdb

middleware — 中间件

中间件说明
report.ts请求响应日志记录
authorize_user.ts用户身份授权校验
operate_log.ts操作日志记录
repeat_submit.ts防重复提交
rate_limit.ts接口限流

reqctx — 请求上下文

请求级别的上下文信息处理,获取当前登录用户、客户端 IP 等。

resp — 响应封装

统一的响应数据结构封装。

token — JWT 令牌

JWT 令牌的生成、刷新、解析处理。

utils — 工具函数

仅依赖 npm 库,不与框架绑定的纯函数工具。

src/modules

按功能领域划分模块,每个模块遵循分层架构。

modules
├── auth                    认证模块(登录、登出、令牌刷新)
│   ├── controller          接口路由
│   ├── model               数据模型
│   └── service             业务逻辑
├── common                  通用模块(验证码、通用接口)
│   └── controller
├── demo                    示例模块
│   ├── controller
│   ├── model
│   └── service
├── monitor                 监控模块(在线用户、定时任务、服务监控)
│   ├── controller
│   ├── model
│   ├── processor           队列任务处理
│   ├── repository
│   └── service
└── system                  系统模块(用户、角色、菜单、部门、字典等)
    ├── controller
    ├── model
    │   └── vo              视图对象
    ├── repository
    └── service

分层说明

目录职责
控制层controller定义路由,接收验证参数,调用 service
数据模型model数据库表字段映射,或业务数据结构
视图对象model/vo接口响应的数据结构定义
业务逻辑service核心业务处理,条件判断、依赖调用
数据存储repository数据库 CRUD 操作,事务处理
队列处理processorBullMQ 异步任务处理

controller 示例

import { Controller, Get, Inject } from "@midwayjs/core";
import { PreAuthorize } from "../../framework/decorator/authorize_user";
import { RateLimit } from "../../framework/middleware/rate_limit";

@Controller("/system/user")
export class SysUserController {
  @Inject()
  private sysUserService: SysUserService;

  @Get("/list")
  @PreAuthorize({ hasPermissions: ["system:user:list"] })
  @RateLimit({ time: 60, count: 100 })
  async list() {
    return await this.sysUserService.list();
  }
}

数据库事务

使用 TypeORM QueryRunner 管理事务:

import { Inject, Provide, Singleton } from "@midwayjs/core";
import { DataSource } from "typeorm";

@Provide()
@Singleton()
export class SysUserRepository {
  @Inject()
  private dataSource: DataSource;

  async transferAmount(fromId: number, toId: number, amount: number): Promise<boolean> {
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();
    try {
      await queryRunner.query("UPDATE sys_user SET balance = balance - ? WHERE id = ?", [amount, fromId]);
      await queryRunner.query("UPDATE sys_user SET balance = balance + ? WHERE id = ?", [amount, toId]);
      await queryRunner.commitTransaction();
      return true;
    } catch (err) {
      await queryRunner.rollbackTransaction();
      throw new Error("服务数据异常");
    } finally {
      await queryRunner.release();
    }
  }
}

队列任务处理

import { Processor, IProcessor } from "@midwayjs/bullmq";

@Processor("simple")
export class SimpleProcessor implements IProcessor {
  async execute(options: any) {
    // options 获取任务执行时传入的参数
    // 返回结果用于记录执行结果
    return options;
  }
}

src/typings

全局类型定义。

文件说明
commont.ts通用类型声明
entities.tsTypeORM 实体注册列表(打包需要显式注册)
processor.ts队列处理器类型

test

Jest 测试用例。

npm run test    # 运行测试
npm run cov     # 测试覆盖率