公司内部项目模板 - 基于 Midway.js + Vue3 + TypeScript + TypeORM + Bootstrap5 的现代化全栈开发模板,提供完整的用户管理、权限控制、文件上传等功能。
template/
├── bin/ # 脚本文件
│ ├── init.js # 项目初始化脚本(自动安装依赖)
│ ├── dev.sh # 开发环境启动脚本
│ ├── build.sh # 构建脚本
│ └── deploy.sh # 部署脚本
├── src/ # 后端源码
│ ├── config/ # 配置文件
│ │ ├── config.default.ts # 默认配置
│ │ ├── config.local.ts # 本地开发配置
│ │ └── devops.config.ts # 部署配置(路由前缀等)
│ ├── controller/ # 控制器层(处理HTTP请求)
│ │ ├── admin.controller.ts # 管理端接口代理
│ │ ├── user.controller.ts # 用户管理接口
│ │ ├── session.controller.ts # 登录/登出接口
│ │ └── home.controller.ts # 页面渲染入口
│ ├── service/ # 业务逻辑层
│ │ ├── user.service.ts # 用户业务逻辑
│ │ ├── session.service.ts # 会话管理逻辑
│ │ └── account.service.ts # 账户服务(远程API)
│ ├── model/ # 数据模型 (TypeORM 实体)
│ │ └── user.entity.ts # 用户实体定义
│ ├── dto/ # 数据传输对象(请求参数验证)
│ │ └── user.dto.ts # 用户相关DTO
│ ├── filter/ # 异常过滤器
│ │ ├── default.filter.ts # 全局异常处理
│ │ └── notfound.filter.ts # 404处理
│ ├── guard/ # 守卫(预留目录)
│ ├── interface/ # 类型定义
│ ├── lib/ # 工具库
│ └── configuration.ts # 应用入口配置
├── web/ # 前端源码
│ ├── src/
│ │ ├── platform/ # 平台核心(入口、根组件)
│ │ ├── pages/ # 页面组件
│ │ ├── components/ # 公共组件
│ │ │ ├── dataGrid/ # 数据表格组件
│ │ │ ├── loading/ # 加载状态组件
│ │ │ ├── modal/ # 模态框组件
│ │ │ └── toast/ # 消息提示组件
│ │ ├── service/ # API 服务层
│ │ │ ├── base.ts # 基础请求封装
│ │ │ ├── account.ts # 账户相关API
│ │ │ └── mock/ # Mock数据
│ │ ├── stores/ # 状态管理 (Pinia)
│ │ │ └── session.ts # 登录态管理
│ │ ├── utils/ # 工具函数
│ │ ├── base/ # 基础层(事件总线、配置等)
│ │ ├── domain/ # 领域层
│ │ ├── directives/ # Vue指令
│ │ └── assets/ # 静态资源
│ ├── public/ # 静态资源(构建后复制)
│ ├── view/ # HTML 模板入口
│ └── vite.config.ts # Vite 配置
├── data/ # 数据文件
│ └── db_myproject_t_user.sql # 数据库初始化脚本
├── logs/ # 日志目录(运行时生成)
├── dist/ # 构建输出
├── typings/ # 类型定义
├── skills/ # 开发规范文档
│ ├── SKILL.md # 主入口文档
│ ├── coding-standards.md # 编码规范
│ ├── fullstack/ # 全栈开发技能
│ ├── database/ # 数据库开发技能
│ ├── frontend/ # 前端开发技能
│ └── backend/ # 后端开发技能
├── .env # 环境变量(需从 .tpl.env 复制)
├── .tpl.env # 环境变量模板
├── bootstrap.js # 生产环境启动入口
├── package.json # 项目依赖和脚本
└── README.md # 本文档
git clone <repository-url>
cd template
# 自动检测并使用 pnpm(优先)或 npm 安装所有依赖
npm run init
# 安装后端依赖
pnpm install
# 安装前端依赖
cd web && pnpm install && cd ..
复制环境变量模板并修改:
cp .tpl.env .env
编辑 .env 文件,配置必要参数:
# ===== 服务配置 =====
PORT=8000 # 服务端口
TITLE=管理系统 # 系统标题
PREFIX=my-project # URL前缀(部署路径)
# ===== 数据库配置 =====
# 设置 DISABLE_DB=true 可无数据库启动(用于前端开发)
DISABLE_DB=false
DB_HOST=localhost # 数据库地址
DB_PORT=3306 # 数据库端口
DB_USERNAME=root # 数据库用户名
DB_PASSWORD=your_password # 数据库密码
DB_DATABASE=db_myproject # 数据库名称
# ===== 安全配置(必填) =====
SESSION_SECRET=your-secret-key-at-least-32-chars # Session密钥,至少32字符
# ===== API配置 =====
API_URL= # 后端API地址(留空使用本地验证)
BASE_SERVER_URL= # 远程基础服务地址(可选)
# ===== 腾讯云配置(可选) =====
TENCENT_CREDENTIAL_SECRETID= # 腾讯云SecretId
TENCENT_CREDENTIAL_SECRETKEY= # 腾讯云SecretKey
TENCENT_COS_DEFAULT_BUCKET= # COS存储桶名称
TENCENT_COS_DEFAULT_REGION= # COS地域
# 创建数据库
mysql -u root -p -e "CREATE DATABASE db_myproject DEFAULT CHARSET utf8mb4"
# 导入初始数据(包含admin管理员账号)
mysql -u root -p db_myproject < data/db_myproject_t_user.sql
默认管理员账号: admin / admin123
npm run dev
这将同时启动前后端开发服务器,前端支持热更新。
# 终端1:启动后端 (端口 8000)
npm run dev:midway
# 终端2:启动前端 (端口 5173)
npm run dev:vue
@decorators.checkLogin()| 功能 | 接口 | 描述 |
|---|---|---|
| 用户搜索 | POST /api/user/search | 分页获取用户列表,支持多字段筛选 |
| 用户详情 | POST /api/user/getUserDetail | 获取用户详细信息 |
| 创建用户 | POST /api/user/create | 创建新用户(需管理员权限) |
| 更新用户 | POST /api/user/update | 更新用户信息(需管理员权限) |
| 修改密码 | POST /api/user/updatePassword | 修改用户密码 |
| 设置状态 | POST /api/user/setStatus | 启用/禁用用户(需管理员权限) |
| 上传头像 | POST /api/user/uploadAvatar | 上传用户头像到腾讯云COS |
// src/controller/example.controller.ts
import { Controller, Get, Post, Provide, Body } from '@midwayjs/core';
import { BaseController, decorators } from '@cicctencent/midwayjs-base';
@Provide()
@Controller('/api/example')
export class ExampleController extends BaseController {
@Get('/list')
async list() {
return { ret: 0, data: [], msg: 'success' };
}
@Post('/create')
@decorators.checkLogin(true) // 需要登录
async create(@Body() data: CreateDTO) {
// 业务逻辑
return { ret: 0, msg: '创建成功' };
}
}
// src/service/example.service.ts
import { Provide, Inject } from '@midwayjs/core';
import { BaseService } from '@cicctencent/midwayjs-base';
import { InjectDataSource } from '@midwayjs/typeorm';
import { DataSource, Repository } from 'typeorm';
import ExampleEntity from '../model/example.entity';
@Provide()
export class ExampleService extends BaseService {
@InjectDataSource('default')
dataSource: DataSource;
get model(): Repository<ExampleEntity> {
return this.dataSource.getRepository(ExampleEntity);
}
async search(params: SearchParams) {
// 查询逻辑
return await this.model.find({ where: params });
}
}
// src/model/example.entity.ts
import BaseEntity from '@fefeding/common/dist/models/base/baseORM';
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity('t_example')
export default class ExampleEntity extends BaseEntity {
@PrimaryGeneratedColumn({ name: 'id', comment: '自增主键' })
id: number;
@Column({ name: 'Fname', length: 100, comment: '名称' })
name: string;
@Column({ name: 'Fstatus', type: 'smallint', default: 1, comment: '状态' })
status: number;
}
// src/dto/example.dto.ts
import { Rule, RuleType } from '@midwayjs/validate';
@Rule(RuleType.object())
export class CreateExampleDTO {
@Rule(RuleType.string().min(2).max(100).required())
name: string;
@Rule(RuleType.number().integer().positive().optional())
status?: number;
}
<!-- web/src/pages/example.vue -->
<template>
<div class="container">
<h1>示例页面</h1>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useSessionStore } from '@/stores/session';
const sessionStore = useSessionStore();
onMounted(() => {
console.log('页面加载完成');
});
</script>
// web/src/service/example.ts
import { request } from './base';
export async function getExampleList(params: any) {
return request('/api/example/list', params);
}
export async function createExample(data: any) {
return request('/api/example/create', data);
}
import { useSessionStore } from '@/stores/session';
const sessionStore = useSessionStore();
// 检查登录状态
if (sessionStore.isLoggedIn) {
console.log('当前用户:', sessionStore.userName);
}
// 更新用户信息
sessionStore.updateUserInfo({ name: '新名称' });
npm run build
构建完成后,产物在 dist/ 目录。
# 使用 PM2 启动(推荐)
npm start
# 或直接启动
node bootstrap.js
npm run docker
docker run -d -p 8000:8000 -v $(pwd)/.env:/app/.env --name web-server base-server
npm run tars:deploy
interface ApiResponse<T> {
ret: number; // 0 成功,非 0 失败
data?: T; // 响应数据
msg: string; // 提示信息
}
| 错误码 | 描述 |
|---|---|
| 0 | 成功 |
| 1 | 业务错误 |
| 1000 | 未知错误 |
| 50001 | 登录态失效 |
| 接口 | 方法 | 路径 | 描述 | 权限 |
|---|---|---|---|---|
| 账号登录 | POST | /api/session/loginByAccount | 账号密码登录 | 无需登录 |
| 微信登录 | POST | /api/session/loginByWx | 微信扫码登录 | 无需登录 |
| 登出 | POST | /api/session/logout | 退出登录 | 无需登录 |
| 获取会话 | POST | /api/session/getLoginSession | 获取当前登录态 | 无需登录 |
| 授权码登录 | POST | /api/session/loginByCode | 临时授权码登录 | 无需登录 |
| 接口 | 方法 | 路径 | 描述 | 权限 |
|---|---|---|---|---|
| 用户搜索 | POST | /api/user/search | 分页搜索用户 | 需要登录 |
| 用户详情 | POST | /api/user/getUserDetail | 获取用户详情 | 需要登录 |
| 创建用户 | POST | /api/user/create | 创建新用户 | 管理员 |
| 更新用户 | POST | /api/user/update | 更新用户信息 | 管理员 |
| 修改密码 | POST | /api/user/updatePassword | 修改密码 | 需要登录 |
| 设置状态 | POST | /api/user/setStatus | 启用/禁用用户 | 管理员 |
| 上传头像 | POST | /api/user/uploadAvatar | 上传头像 | 需要登录 |
# 后端单元测试
npm test
# 测试覆盖率
npm run cov
# 代码规范检查
npm run lint
# 自动修复
npm run lint:fix
| 命令 | 描述 |
|---|---|
npm run init | 一键安装所有依赖 |
npm run dev | 启动开发环境(前后端) |
npm run dev:midway | 仅启动后端 |
npm run dev:vue | 仅启动前端 |
| 命令 | 描述 |
|---|---|
npm run build | 构建生产版本 |
npm run build:vue | 仅构建前端 |
npm run build:midway | 仅构建后端 |
| 命令 | 描述 |
|---|---|
npm start | PM2 启动生产服务 |
npm restart | 重启服务 |
npm stop | 停止服务 |
npm run deploy | 完整部署流程 |
npm run zip | 打包为 server.zip |
npm run docker | 构建 Docker 镜像 |
| 文件 | 用途 |
|---|---|
config.default.ts | 默认配置(数据库、Session、COS等) |
config.local.ts | 本地开发配置(视图路径、静态文件) |
devops.config.ts | 部署配置(URL前缀、系统标题) |
| 文件 | 用途 |
|---|---|
vite.config.ts | Vite 构建配置 |
tsconfig.json | TypeScript 配置 |
| 变量 | 必填 | 描述 |
|---|---|---|
PORT | 否 | 服务端口,默认 7001 |
SESSION_SECRET | 是 | Session密钥,至少32字符 |
DB_HOST | 否 | 数据库地址 |
DB_DATABASE | 否 | 数据库名称 |
DISABLE_DB | 否 | 设为 true 可无数据库启动 |
PREFIX | 否 | URL前缀(部署路径) |
API_URL | 否 | 远程API地址 |
TITLE | 否 | 系统标题 |
详见 skills/README.md 和 skills/coding-standards.md
feat: 新功能
fix: 修复bug
docs: 文档更新
style: 代码格式调整
refactor: 重构
test: 测试相关
chore: 构建/工具链相关
A: 设置 DISABLE_DB=true,适用于纯前端开发场景。
A: 修改 .env 中的 PREFIX 变量,如 PREFIX=my-app。
A: 使用 @decorators.checkLogin(true) 装饰器,或在配置中添加 auth.ignores 规则。
A: 检查 SESSION_SECRET 是否正确配置,确保 Session 存储正常。
A: 后端默认支持 CORS,可在 config.default.ts 中详细配置。
A: 配置 BASE_SERVER_URL 指向远程服务地址,系统会自动使用远程验证。
如有问题,请联系项目维护者或提交 Issue。
版本: 2.0.0
更新日期: 2026-05-21
作者: fefeding