Hello,大家好,我是Carole。本日给大家分享一下我开源的一个项目carole-admin。一款Nestjs+Prisma+Vue3前后端分离的快速开发平台。(前端基于若依)
平台简介
carole-admin 是一款Nestjs+Prisma+Vue+Vite前后端分离的全栈快速开发平台, 前端基于若依。
- 前端采用Vue3、Element-Plus、Vite。
- 后端采用Nest、Prisma、ioredis & Jwt。
- 权限认证使用Jwt,支持多终端认证系统。
- 支持加载动态权限菜单,多方式轻松权限控制。
- 支持接口限流
- 高服从开发,使用代码天生器可以一键天生前后端代码。
项目
演示地址:https://carole.top
默认有两个用户: admin的暗码为carole test的暗码为123456
github: https://github.com/Carole007/carole-admin
gitee: https://gitee.com/Carole007/carole-admin
情况
- nodejs: v20.12.0
- mysql: 8.0.12
- redis
开始
- # 克隆项目
- git clone https://github.com/Carole007/carole-admin.git
- # 导入sql
- # 启动redis
- # 进入项目目录
- cd carole-admin/server
- # 安装依赖
- npm i
- # 生生当前平台的引擎 生成失败多试几次,或者换个网络
- npx prisma generate
- # 修改server/src/里面的.env数据库连接配置,以及config.ts里面的redis连接配置,文件上传路径。
- # 启动服务
- npm run start:dev
- # 前台
- cd carole-admin/front
- npm i
- npm run dev
复制代码 内置功能
- 用户管理:用户是系统操纵者,该功能主要完成系统用户配置。
- 部分管理:配置系统组织机构。
- 岗位管理:配置系统用户所属担当职务。
- 菜单管理:配置系统菜单,操纵权限,按钮权限标识等。
- 角色管理:角色菜单权限分配、设置角色按机构举行数据范围权限分别。
- 字典管理:对系统中经常使用的一些较为固定的数据举行维护。
- 参数管理:对系统动态配置常用参数。
- 关照公告:系统关照公告信息发布维护。
- 登录日志:系统登录日志记录查询包罗登录非常。
- 代码天生:前后端代码的天生(js、vue、sql)支持CRUD下载 。
- 系统接口:根据业务代码主动天生相关的api接口文档。
- 在线用户:当前系统中活泼用户状态监控。
- 服务监控:监督当前系统CPU、内存、磁盘、堆栈等相关信息。
- 缓存监控:对系统的缓存信息查询,命令统计等。
演示图
文档
主要文件布局
- server #系统后端
- front #系统前端
- server/src目录
- ├─admin #系统管理模块
- │ ├─gen #代码生成
- │ └─system #系统代码
- │ └─admin.module.ts #系统模块配置
-
- ├─common #工具类
- │ ├─decorator #自定义注解
- │ ├─filter #异常处理
- │ ├─guard
- │ │ ├─permission #权限校验
- │ ├─middleware #中间件
- │ │ └─auth #身份校验
- │ ├─pipe #自定义管道
- │ ├─prisma-client #prisma客户端
- │ ├─result #返回对象
- │ ├─service
- │ │ ├─auth #身份相关处理逻辑
- │ │ ├─gen #代码生成逻辑
- │ │ │ └─gen-template #代码模板
- │ └─utils #通用工具
-
- ├─prisma
- │ └─schema #数据库模型定义
- │ └─schema.prisma #prisma主文件
-
- ├─schedule #定时任务
-
- ├─ │ ├─.env #环境变量配置, 密码
- ├─ │ ├─main.ts #主文件
- ├─ │ ├─config.ts #系统配置文件
- ├─ │ ├─app.module.ts #系统主模块
复制代码 配置文件
- import * as dotenv from "dotenv";
- import { join } from "path";
- import { config } from "./common/types/config";
- dotenv.config({ path: join(__dirname, ".env") })
- export const Config: config = {
- //服务器的HTTP端口,默认为3000
- port: 3000,
- //# 应用的访问路径前缀
- contextPath: "/v1",
- swagger: {
- //是否启用swagger
- enable: true,
- //接口文档路径
- prefix: "/api"
- },
- captcha: {
- //验证码类型 math或text
- mode: "math",
- //验证码过期时间
- expiresIn: 60 * 2,
- },
- //接口限流 2分钟内同一个接口允许60次请求
- rateLimit: {
- ttl: 2 * 60 * 1000,
- limit: 60,
- },
- crypto: {
- //密码加密秘钥
- psdSecret: process.env.psdSecret || "carole123456",
- },
- token: {
- // token加密秘钥
- secret: process.env.tokenSecret || "carole123456",
- //过期时间秒
- expiresIn: 60 * 60 * 24
- },
- prisma: {
- //是否显示执行的sql指令
- logEnable: false,
- //显示那些日志
- log: ['query', 'info', 'warn', 'error']
- },
- //redis连接配置
- redis: {
- //主机地址
- host: '127.0.0.1',
- //端口
- port: 6379,
- //数据库
- db: 5,
- //密码
- //password:""
- },
- upload: {
- //上传文件存储基目录 请设置一个绝对路径
- path: "d:/uploads",
- config: {
- img: {
- fileSize: 2 * 1024 * 1024,
- files: 1,
- fieldSize: 0.5 * 1024 * 1024,
- fields: 100,
- fieldNameSize: 100,
- parts: 100,
- headerPairs: 100,
- },
- file: {
- fileSize: 100 * 1024 * 1024,
- files: 10,
- fieldSize: 0.5 * 1024 * 1024,
- fields: 100,
- fieldNameSize: 100,
- parts: 100,
- headerPairs: 100,
- },
- },
- },
- //生成配置
- gen: {
- //作者
- author: "carole",
- //默认生成模块
- packageName: "admin",
- //子模块目录
- moduleName: "system",
- //是否去除表前缀,默认是false
- autoRemovePre: false,
- //表前缀(生成类名不会包含表前缀,多个用逗号分隔)
- tablePrefix: ["sys_"]
- },
- //邮件发送配置
- mail: {
- //是否启用邮箱
- enable: false,
- //超时设置, 30秒未发送邮件,则返回失败
- timeout: 30 * 1000,
- config: {
- //邮箱服务器 qq:smtp.qq.com 网易: smtp.163.com
- host: process.env.mailHost,
- //端口
- port: 465,
- auth: {
- //用户名
- user: process.env.mailUser,
- //密码
- pass: process.env.mailPass,
- },
- // 端口465设置true, 其他false
- secure: true,
- tls: {
- //建立 TLS 连接时是否应该拒绝未经授权的服务器证书
- rejectUnauthorized: false,
- },
- },
- },
- };
复制代码
- 情况变量配置 src/.env文件
- DATABASE_URL="mysql://root:123456@localhost:3306/carole" #url格式 mysql://用户名:密码@ip:端口/数据库?参数charset=utf8mb4
- psdSecret = "carole123456"#密码加密秘钥 加密算法:HmacSHA256
- tokenSecret = "carole123456" #token加密秘钥
- mailHost = ""#邮箱服务器 qq:smtp.qq.com 网易: smtp.163.com
- mailUser = "" #发件邮箱账号
- mailPass = "" #发件邮箱密码
复制代码 配置注意点
数据库中的用户暗码使用默认秘钥加密,假如你修改了暗码加密秘钥,请手动实行 server\test\password.js获取新暗码,并手动更新数据库。
权限注解
注解权限控制
- @RequirePermission当前用户必要拥有特定的权限时,才能实行被该注解标注的方法。假如当前用户不具有这样的权限,则方法不会被实行。
- @RequireRole当前用户必须拥有所有指定的角色时,才能访问被该注解标注的方法。假如当前用户不拥有指定的角色,则方法不会实行。
@RequireRole
@RequireRole注解用于配置接口要求用户拥有指定角色才可访问
参数类型形貌valueString角色 示例:以下代码表示必须拥有admin角色才可访问
- @RequireRole("admin")
- async test() {
- return Result.ok()
- }
复制代码 @RequirePermission
@RequirePermission注解用于配置接口要求用户拥有指定权限才可访问
参数类型形貌valueString权限 示例:以下代码表示必须拥有system:user:remove角色才可访问
- @RequirePermission("system:user:remove")
- async test() {
- return Result.ok()
- }
复制代码 Prisma相关
prisma官方文档
server目录下的两个Prisma的bat脚本功能解释
更新prisma的model.bat
- 此脚本用于当你已经编写好Prisma的model文件,但数据库布局发生了更改时。它可以同步数据库的最新布局到Prisma的schema文件中。
相当于实行 npx prisma db pull && npx prisma generate
驼峰天生prisma的model.bat
- 此脚本用于从数据库中天生Prisma的model定义,适用于数据库表没有在Prisma中的model定义过。(代码天生模板会使用驼峰定名法,并主动添加字段和表的map映射关系。)
相当于实行 npx prisma db pull 然后把天生Model字段名改为驼峰 实行 npx prisma generate
- 天生之后会在src/prisma目录中有个introspected.prisma文件,可以更改名字并移动到 src/prisma/schema里面。
固然,你也可以手动实行Prisma指令之后修改Model。
注意
- 实行时,确保model都写好表和字段的映射关系了 @@map映射表 @Map映射字段
model名称使用PascalCase定名 好比: test -> Test, sys_config -> SysConfig, 假如你不使用代码天生器,无需这样。
示例:
- model SysConfig {
- configId Int @id @default(autoincrement()) @map("config_id")
- configName String? @default("") @map("config_name") @db.VarChar(100)
- configKey String? @default("") @map("config_key") @db.VarChar(100)
- configValue String? @default("") @map("config_value") @db.VarChar(500)
- configType String? @default("N") @map("config_type") @db.Char(1)
- createBy String? @default("") @map("create_by") @db.VarChar(64)
- createTime String? @map("create_time") @db.VarChar(25)
- updateBy String? @default("") @map("update_by") @db.VarChar(64)
- updateTime String? @map("update_time") @db.VarChar(25)
- remark String? @map("remark") @db.VarChar(500)
- @@map("sys_config")
- }
复制代码
- prisma中日期类型字段插入时存在时差问题
办理办法:把sql中的日期类型改成字符串,插入更新时手动设置时间
- 当数据库使用 long 类型时,查询出来的数据会主动转换为 bigint。在将这些数据转换为 JSON 时大概会出现问题。可以转换为字符串返回前端,但前端传来数据后端也必要转换为long才能正常使用。
当数字超出±(2^53 - 1)转换为Number也会出现问题
- BigInt.prototype.toJSON = function(){
- return this.toString()
- }
复制代码 假如您考虑更改数据类型,以下是两种大概的办理方案: 1.使用Int 无符号最大可以存4,294,967,295多条数据,作为主键一般场景完全够用了 2.使用字符串,存uuid (无穷制)
代码天生使用
1、在prisma\schema写好对应表的Model,字段名驼峰映射
2、登录系统(系统工具 -> 代码天生 -> 导入对应表)
3、代码天生列表中找到必要表(可预览、编辑、同步、删除天生配置)
4、点击天生代码会得到一个carole.zip实行sql文件天生菜单权限,按照包内目录布局复制到本身的项目中
5、修改对应模块的module.ts文件,在providers中注册天生的Service,controllers注册天生的Controller类
代码天生支持编辑、预览、同步
预览:对天生的代码提前预览,防止出现一些不符合预期的情况。
同步:对原表的字段举行同步,包括新增、删除、修改的字段处理。
修改:对天生的代码基本信息、字段信息、天生信息做一系列的调整。
定时任务
@nestjs/schedule文档
使用定时任务非常轻易,只需在 server\src\schedule\index.ts中添加添加必要实行的方法并加上@Cron注解并携带cron表达式即可
示例:
- //cron任务,每隔两秒执行一次
- @Cron('*/2 * * * * *')
- testCron() {
- console.log("cron excute...")
- }
复制代码 接口限流
@nestjs/throttler文档
默认所有接口2分钟内都只答应60次请求,可以在config.ts里面配置rateLimit, 单独定义某个接口,只需加上@Throttle根据本身必要配置即可
示例:
- //1个小时之内只能请求8次
- @Throttle({
- default: {
- limit: 8,
- ttl: 1000 * 60 * 60
- }
- })
- async test1() {
- return Result.ok()
- }
- //5s内只能请求一次
- @Throttle({
- default: {
- limit: 1,
- ttl: 1000 * 5
- }
- })
- async test2() {
- return Result.ok()
- }
复制代码 发送邮件
- 修改.env里面的 邮箱毗连账号暗码,和服务器地址
- 按需修改config.ts的mail配置项,enable为true
- 参考server\src\common\utils\emial.ts文件使用
部署
- #后端
- cd server && npm run build
- # 把package.json移动到dist目录,上传dist目录到服务器,修改配置
- node main.js
- #前端
- npm run build:prod
复制代码 求Star!!!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |