cool-admin-midway/.cursorrules
2025-01-26 12:37:27 +08:00

286 lines
8.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 项目背景
- 数据库MySQL、Sqlite、Postgres、Typeorm
- 语言TypeScript、JavaScript、CommonJS
- 框架Koa.js、midway.js、cool-admin-midway
- 项目版本8.x
# 目录
项目目录:
├── .vscode(代码片段,根据关键字可以快速地生成代码)
├── public(静态资源文件如js、css或者上传的文件)
├── src
│ └── comm(通用库)
│ └── modules(项目模块)
│ └── config
│ │ └── config.default.ts(默认配置,不区分环境,都生效)
│ │ └── config.local.ts(本地开发配置对应npm run dev)
│ │ └── config.prod.ts(生产环境配置对应npm run start)
│ └── configuration.ts(midway的配置文件)
│ └── welcome.ts(环境的controller)
│ └── interface.ts(类型声明)
├── package.json(依赖管理,项目信息)
├── bootstrap.js(生产环境启动入口文件可借助pm2等工具多进程启动)
└── ...
模块目录
├── modules
│ └── base(基础的权限管理系统)
│ │ └── controller(api接口)
│ │ └── dto(参数校验)
│ │ └── entity(实体类)
│ │ └── middleware(中间件)
│ │ └── schedule(定时任务)
│ │ └── service(服务,写业务逻辑)
│ │ └── config.ts(必须,模块的配置)
│ │ └── db.json(可选,初始化该模块的数据)
│ │ └── menu.json(可选,初始化该模块的菜单)
# 核心
- Controller
```ts
import { Get, Provide } from "@midwayjs/core";
import { CoolController, BaseController } from "@cool-midway/core";
import { BaseSysUserEntity } from "../../../base/entity/sys/user";
import { DemoAppGoodsEntity } from "../../entity/goods";
/**
* 商品
*/
@Provide()
@CoolController({
// 添加通用CRUD接口
api: ["add", "delete", "update", "info", "list", "page"],
// 设置表实体
entity: DemoAppGoodsEntity,
// 向表插入当前登录用户ID
insertParam: (ctx) => {
return {
// 获得当前登录的后台用户ID需要请求头传Authorization参数
userId: ctx.admin.userId,
};
},
// 操作crud之前做的事情 @cool-midway/core@3.2.14 新增
before: (ctx) => {
// 将前端的数据转JSON格式存数据库
const { data } = ctx.request.body;
ctx.request.body.data = JSON.stringify(data);
},
// info接口忽略价格字段
infoIgnoreProperty: ["a.price"],
// 分页查询配置
pageQueryOp: {
// 让title字段支持模糊查询
keyWordLikeFields: ["a.title"],
// 让type字段支持筛选请求筛选字段与表字段一致是情况
fieldEq: ["a.type"],
// 多表关联,请求筛选字段与表字段不一致的情况
fieldEq: [{ column: "a.id", requestParam: "id" }],
// 指定返回字段,注意多表查询这个是必要的,否则会出现重复字段的问题
select: ["a.*", "b.name", "a.name AS userName"],
// 4.x置为过时 改用 join 关联表用户表
leftJoin: [
{
entity: BaseSysUserEntity,
alias: "b",
condition: "a.userId = b.id",
},
],
// 4.x新增
join: [
{
entity: BaseSysUserEntity,
alias: "b",
condition: "a.userId = b.id",
type: "innerJoin",
},
],
// 4.x 新增 追加其他条件
extend: async (find: SelectQueryBuilder<DemoGoodsEntity>) => {
find.groupBy("a.id");
},
// 增加其他条件
where: async (ctx) => {
// 获取body参数
const { a } = ctx.request.body;
return [
// 价格大于90
["a.price > :price", { price: 90.0 }],
// 满足条件才会执行
["a.price > :price", { price: 90.0 }, "条件"],
// 多个条件一起
[
"(a.price = :price or a.userId = :userId)",
{ price: 90.0, userId: ctx.admin.userId },
],
];
},
// 可选添加排序默认按createTime Desc排序
addOrderBy: {
price: "desc",
},
},
})
export class DemoAppGoodsController extends BaseController {
/**
* 其他接口
*/
@Get("/other")
async other() {
return this.ok("hello, cool-admin!!!");
}
}
```
注意:
- CoolController的entityalias 为 "a";
- 如果是多表查询,必须设置 select 参数,否则会出现重复字段的错误,因为每个表都继承了 BaseEntity至少都有 id、createTime、updateTime 三个相同的字段;
- keyWordLikeFields、fieldEq等配置哪个字段都需要有对应的别名
- Entity
```ts
// BaseEntity的路径是固定不能修改
import { BaseEntity } from '../../base/entity/base';
import { Column, Entity, Index } from 'typeorm';
/**
* demo模块-用户信息
*/
// 表名必须包含模块固定格式模块_
@Entity('demo_user_info')
// DemoUserInfoEntity是模块+表名+Entity
export class DemoUserInfoEntity extends BaseEntity {
@Index()
@Column({ comment: '手机号', length: 11 })
phone: string;
@Index({ unique: true })
@Column({ comment: '身份证', length: 50 })
idCard: string;
// 生日只需要精确到哪一天所以type:'date',如果需要精确到时分秒,应为'datetime'
@Column({ comment: '生日', type: 'date' })
birthday: Date;
@Column({ comment: '状态', dict: ['禁用', '启用'], default: 1 })
status: number;
@Column({ comment: '分类', dict: ['普通', '会员', '超级会员'], default: 0, type: 'tinyint' })
type: number;
// 由于labels的类型是一个数组所以Column中的type类型必须得是'json'
@Column({ comment: '标签', nullable: true, type: 'json' })
labels: string[];
@Column({
comment: '余额',
type: 'decimal',
precision: 12,
scale: 2,
})
balance: number;
@Column({ comment: '备注', nullable: true })
remark: string;
@Column({ comment: '简介', type: 'text', nullable: true })
summary: string;
@Column({ comment: '省', length: 50 })
province: string;
@Column({ comment: '市', length: 50 })
city: string;
@Column({ comment: '区', length: 50 })
district: string;
@Column({ comment: '详细地址', length: 255 })
address: string;
}
```
注意:
- 禁止使用外键如ManyToOne、JoinColumn等
- comment需要简短如班级表的名称不要叫班级名称直接叫名称
- dict如果遇到可选项如状态、类型等需要配置
- BaseEntity的路径是固定不能修改
- Service
```ts
import { Init, Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
/**
* 描述
*/
@Provide()
export class XxxService extends BaseService {
@InjectEntityModel(实体)
xxxEntity: Repository<实体>;
// 获得ctx
@Inject()
ctx;
@Init()
async init() {
await super.init();
this.setEntity(this.xxxEntity);
}
/**
* 其它方法
*/
async xxx() {}
}
```
- 自动路由
规则: /controller 文件夹下的文件夹名或者文件名/模块文件夹名/方法名
// 模块目录
├── modules
│ └── demo(模块名)
│ │ └── controller(api接口)
│ │ │ └── app(参数校验)
│ │ │ │ └── goods.ts(商品的controller)
│ │ │ └── pay.ts(支付的controller)
│ │ └── config.ts(必须,模块的配置)
│ │ └── init.sql(可选初始化该模块的sql)
生成的路由前缀为: /pay/demo/xxx(具体的方法)与/app/demo/goods/xxx(具体的方法)
- config.ts
```ts
import { ModuleConfig } from '@cool-midway/core';
/**
* 模块配置
*/
export default () => {
return {
// 模块名称
name: 'xxx',
// 模块描述
description: 'xxx',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序默认为0值越大越优先加载
order: 0,
} as ModuleConfig;
};
```
# 其它
- 根据需要进行必要的关联表查询;
- 禁止出现import 但是没有使用的情况;
- 所有代码需有类级注释;