初始版本,目前线上可用

This commit is contained in:
2025-11-19 12:49:16 +08:00
commit cb7f1c45e8
178 changed files with 30336 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
import { getConnection, Between, Brackets } from "typeorm";
import { Request } from "express";
type paginationType<T> = {
list: T[];
total: number;
pageSize: number;
pageNumber: number;
};
const filterKeys = ["pwd"];
const DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
export default async function getBuilderPagination<T>(
entity: Function,
req: Request,
queryParams?: { [key: string]: any }
): Promise<paginationType<T>> {
try {
// 获取分页参数
const { pageSize, pageNumber } = getPaginationParams(req);
const repository = getConnection().manager.getRepository(entity);
const alias = "entity";
// 创建 QueryBuilder
const queryBuilder = repository.createQueryBuilder(alias);
// 处理查询参数
if (queryParams) {
Object.entries(queryParams).forEach(([key, value]) => {
if (!["pageSize", "pageNumber"].includes(key)) {
// 新增非空条件处理
if (value === "NOT_EMPTY") {
queryBuilder.andWhere(
new Brackets((qb) => {
qb.where(`${alias}.${key} IS NOT NULL`).andWhere(
`${alias}.${key} != ''`
);
})
);
}
// 处理日期范围
else if (typeof value === "string" && DATE_REGEX.test(value)) {
const start = new Date(`${value}T00:00:00`);
const end = new Date(`${value}T23:59:59`);
queryBuilder.andWhere(
new Brackets((qb) =>
qb
.where(`${alias}.${key} >= :start`, { start })
.andWhere(`${alias}.${key} <= :end`, { end })
)
);
}
// 处理普通参数
else if (value !== undefined) {
// 处理数组参数(如?status=1,2,3
if (typeof value === "string" && value.includes(",")) {
queryBuilder.andWhere(`${alias}.${key} IN (:...${key})`, {
[key]: value.split(","),
});
}
// 处理普通值
else {
queryBuilder.andWhere(`${alias}.${key} = :${key}`, {
[key]: value,
});
}
}
}
});
}
// 添加排序
queryBuilder.orderBy(`${alias}.createDate`, "DESC");
// 执行分页查询
const [list, total] = await queryBuilder
.skip((pageNumber - 1) * pageSize)
.take(pageSize)
.getManyAndCount();
// 过滤敏感字段
const filteredList = list.map((item: any) => {
const filtered = { ...item };
filterKeys.forEach((key) => delete filtered[key]);
return filtered;
});
return {
list: filteredList,
total,
pageSize,
pageNumber,
};
} catch (err) {
throw new Error(`分页查询出错: ${err.message}`);
}
}
/**
* 获取分页参数
*/
function getPaginationParams(req: Request): {
pageSize: number;
pageNumber: number;
} {
const { pageSize = 10, pageNumber = 1 } =
req.method === "GET" ? req.query : req.body;
return {
pageSize: Math.max(1, parseInt(pageSize as string, 10)),
pageNumber: Math.max(1, parseInt(pageNumber as string, 10)),
};
}

View File

@@ -0,0 +1,97 @@
import { getConnection } from "typeorm";
import { Request } from "express";
type paginationType<T> = {
list: T[] | any[];
total: number;
pageSize: number;
pageNumber: number;
};
const filterKeys = ["pwd"];
/**
*
* @param entites 传入实体类数组以供查询(支持多表)
* @param req express的Request请求体
* @param queryParams 查询参数
* @param aliasMap 表别名映射,键为实体类名,值为别名
* @returns
*/
export default async function MultPagination<T>(
entites: Function[],
req: Request,
queryParams?: { [key: string]: any },
aliasMap: { [key: string]: string } = {}
): Promise<paginationType<T>> {
const { pageSize, pageNumber } = getPaginationParams(req);
// 获取 QueryBuilder
const queryBuilder = getConnection().createQueryBuilder();
// 构造 FROM 部分,支持多表
entites.forEach((entite, index) => {
const alias = aliasMap[entite.name] || `alias${index}`;
if (index === 0) {
queryBuilder.from(entite, alias); // 主表
} else {
queryBuilder.leftJoinAndSelect(entite, alias); // 关联表
}
});
// 构造 WHERE 条件
if (queryParams) {
Object.entries(queryParams).forEach(([key, value]) => {
queryBuilder.andWhere(`${getWhereKey(key, aliasMap)} = :${key}`, {
[key]: value,
});
});
}
// 构造排序
queryBuilder.orderBy("alias0.createDate", "ASC");
// 分页处理
queryBuilder.skip((pageNumber - 1) * pageSize).take(pageSize);
try {
const [list, total] = await queryBuilder.getManyAndCount();
// 过滤敏感数据
list.forEach((item) => {
filterKeys.forEach((key) => {
delete item[key];
});
});
return {
list,
total,
pageSize,
pageNumber,
};
} catch (err) {
throw new Error("分页查询出错:" + err.message);
}
}
function getPaginationParams(req: Request): {
pageSize: number;
pageNumber: number;
} {
const { pageSize = 10, pageNumber = 1 } =
req.method === "GET" ? req.query : req.body;
const realPageSize = Math.max(1, parseInt(pageSize as string, 10));
const realPageNumber = Math.max(1, parseInt(pageNumber as string, 10));
return { pageSize: realPageSize, pageNumber: realPageNumber };
}
// 获取WHERE条件时自动识别别名
function getWhereKey(key: string, aliasMap: { [key: string]: string }) {
for (const alias in aliasMap) {
if (key.startsWith(alias + ".")) {
return key; // 已包含别名
}
}
return `alias0.${key}`; // 默认主表
}

View File

@@ -0,0 +1,83 @@
import { getConnection, Between } from "typeorm";
import { Request } from "express";
type paginationType<T> = {
list: T[] | any[];
total: number;
pageSize: number;
pageNumber: number;
};
const filterKeys = ["pwd"];
const DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
/**
* 处理日期查询参数
*/
function processDateParams(params: { [key: string]: any }): {
[key: string]: any;
} {
const processed = {} as Record<string, any>;
for (const [key, value] of Object.entries(params)) {
if (typeof value === "string" && DATE_REGEX.test(value)) {
// 处理日期范围
const start = new Date(`${value}T00:00:00`);
const end = new Date(`${value}T23:59:59`);
processed[key] = Between(start, end);
} else {
processed[key] = value;
}
}
return processed;
}
/**
* 获取分页参数
*/
function getPaginationParams(req: Request): {
pageSize: number;
pageNumber: number;
} {
const { pageSize = 10, pageNumber = 1 } =
req.method === "GET" ? req.query : req.body;
return {
pageSize: Math.max(1, parseInt(pageSize as string, 10)),
pageNumber: Math.max(1, parseInt(pageNumber as string, 10)),
};
}
/**
* 分页查询封装
*/
export default async function getPagination<T>(
entity: Function,
req: Request,
queryParams?: { [key: string]: any }
): Promise<paginationType<T>> {
try {
const { pageSize, pageNumber } = getPaginationParams(req);
const repository = getConnection().manager.getRepository(entity);
// 处理日期查询参数
const processedWhere = queryParams ? processDateParams(queryParams) : {};
const [list, total] = await repository.findAndCount({
where: processedWhere,
order: { createDate: "DESC" },
skip: (pageNumber - 1) * pageSize,
take: pageSize,
});
// 过滤敏感字段
list.forEach((item) => {
filterKeys.forEach((key) => delete item[key]);
});
return { list, total, pageSize, pageNumber };
} catch (err) {
throw new Error(`分页查询出错: ${err.message}`);
}
}