chore: lib-server

This commit is contained in:
xiaojunnuo
2024-10-03 22:03:49 +08:00
parent a13203fb3f
commit a4e2cc54e6
101 changed files with 936 additions and 223 deletions
@@ -0,0 +1,42 @@
import { Inject } from '@midwayjs/core';
import * as koa from '@midwayjs/koa';
import { Constants } from './constants.js';
export abstract class BaseController {
@Inject()
ctx: koa.Context;
/**
* 成功返回
* @param data 返回数据
*/
ok(data?: any) {
const res = {
...Constants.res.success,
data: undefined,
};
if (data) {
res.data = data;
}
return res;
}
/**
* 失败返回
* @param msg
* @param code
*/
fail(msg: string, code: any) {
return {
code: code ? code : Constants.res.error.code,
msg: msg ? msg : Constants.res.error.code,
};
}
getUserId() {
const userId = this.ctx.user?.id;
if (userId == null) {
throw new Error('Token已过期');
}
return userId;
}
}
@@ -0,0 +1,212 @@
import { ValidateException } from './exception/index.js';
import * as _ from 'lodash-es';
import { PermissionException } from './exception/index.js';
import { Repository } from 'typeorm';
import { Inject } from '@midwayjs/core';
import { TypeORMDataSourceManager } from '@midwayjs/typeorm';
import { EntityManager } from 'typeorm/entity-manager/EntityManager.js';
/**
* 服务基类
*/
export abstract class BaseService<T> {
@Inject()
dataSourceManager: TypeORMDataSourceManager;
abstract getRepository(): Repository<T>;
async transaction(callback: (entityManager: EntityManager) => Promise<any>) {
const dataSource = this.dataSourceManager.getDataSource('default');
await dataSource.transaction(callback as any);
}
/**
* 获得单个ID
* @param id ID
* @param infoIgnoreProperty 忽略返回属性
*/
async info(id, infoIgnoreProperty?): Promise<T | null> {
if (!id) {
throw new ValidateException('id不能为空');
}
const info = await this.getRepository().findOneBy({ id } as any);
if (info && infoIgnoreProperty) {
for (const property of infoIgnoreProperty) {
delete info[property];
}
}
return info;
}
/**
* 非分页查询
* @param options
*/
async find(options) {
return await this.getRepository().find(options);
}
/**
* 删除
* @param ids 删除的ID集合 如:[1,2,3] 或者 1,2,3
*/
async delete(ids) {
if (ids instanceof Array) {
await this.getRepository().delete(ids);
} else if (typeof ids === 'string') {
await this.getRepository().delete(ids.split(','));
} else {
//ids是一个condition
await this.getRepository().delete(ids);
}
await this.modifyAfter(ids);
}
/**
* 新增|修改
* @param param 数据
*/
async addOrUpdate(param) {
await this.getRepository().save(param);
}
/**
* 新增
* @param param 数据
*/
async add(param) {
const now = new Date();
param.createTime = now;
param.updateTime = now;
await this.addOrUpdate(param);
await this.modifyAfter(param);
return {
id: param.id,
};
}
/**
* 修改
* @param param 数据
*/
async update(param) {
if (!param.id) throw new ValidateException('no id');
param.updateTime = new Date();
await this.addOrUpdate(param);
await this.modifyAfter(param);
}
/**
* 新增|修改|删除 之后的操作
* @param data 对应数据
*/
async modifyAfter(data) {}
/**
* 分页查询
* @param query 查询条件 bean
* @param page
* @param order
* @param buildQuery
*/
async page(query, page = { offset: 0, limit: 20 }, order, buildQuery) {
if (page.offset == null) {
page.offset = 0;
}
if (page.limit == null) {
page.limit = 20;
}
const qb = this.getRepository().createQueryBuilder('main');
if (order && order.prop) {
qb.addOrderBy('main.' + order.prop, order.asc ? 'ASC' : 'DESC');
}
qb.addOrderBy('id', 'DESC');
qb.offset(page.offset).limit(page.limit);
//根据bean query
if (query) {
let whereSql = '';
let index = 0;
_.forEach(query, (value, key) => {
if (!value) {
return;
}
if (index !== 0) {
whereSql += ' and ';
}
whereSql += ` main.${key} = :${key} `;
index++;
});
if (index > 0) {
qb.where(whereSql, query);
}
}
//自定义query
if (buildQuery) {
buildQuery(qb);
}
const list = await qb.getMany();
const total = await qb.getCount();
return {
records: list,
total,
offset: page.offset,
limit: page.limit,
};
}
/**
* 分页查询
* @param query 查询条件 bean
* @param order
* @param buildQuery
*/
async list(query, order, buildQuery) {
const qb = this.getRepository().createQueryBuilder('main');
if (order && order.prop) {
qb.orderBy('main.' + order.prop, order.asc ? 'ASC' : 'DESC');
} else {
qb.orderBy('id', 'DESC');
}
//根据bean query
if (query) {
let whereSql = '';
let index = 0;
_.forEach(query, (value, key) => {
if (!value) {
return;
}
if (index !== 0) {
whereSql += ' and ';
}
whereSql += ` main.${key} = :${key} `;
index++;
});
if (index > 0) {
qb.where(whereSql, query);
}
}
//自定义query
if (buildQuery) {
buildQuery(qb);
}
return await qb.getMany();
}
async checkUserId(id: any = 0, userId, userKey = 'userId') {
// @ts-ignore
const res = await this.getRepository().findOne({
// @ts-ignore
select: { [userKey]: true },
// @ts-ignore
where: {
// @ts-ignore
id,
},
});
// @ts-ignore
if (!res || res[userKey] === userId) {
return;
}
throw new PermissionException('权限不足');
}
}
@@ -0,0 +1,52 @@
export const Constants = {
dataDir: './data',
role: {
defaultUser: 3,
},
per: {
//无需登录
guest: '_guest_',
//无需登录
anonymous: '_guest_',
//仅需要登录
authOnly: '_authOnly_',
//仅需要登录
loginOnly: '_authOnly_',
},
res: {
serverError(message: string) {
return {
code: 1,
message,
};
},
error: {
code: 1,
message: 'Internal server error',
},
success: {
code: 0,
message: 'success',
},
validation: {
code: 10,
message: '参数错误',
},
needvip: {
code: 88,
message: '需要VIP',
},
auth: {
code: 401,
message: '您还未登录或token已过期',
},
permission: {
code: 402,
message: '您没有权限',
},
preview: {
code: 10001,
message: '对不起,预览环境不允许修改此数据',
},
},
};
@@ -0,0 +1,61 @@
import { ALL, Body, Post, Query } from '@midwayjs/core';
import { BaseController } from './base-controller.js';
export abstract class CrudController<T> extends BaseController {
abstract getService<T>();
@Post('/page')
async page(
@Body(ALL)
body
) {
const pageRet = await this.getService().page(body?.query, body?.page, body?.sort, null);
return this.ok(pageRet);
}
@Post('/list')
async list(
@Body(ALL)
body
) {
const listRet = await this.getService().list(body, null, null);
return this.ok(listRet);
}
@Post('/add')
async add(
@Body(ALL)
bean
) {
delete bean.id;
const id = await this.getService().add(bean);
return this.ok(id);
}
@Post('/info')
async info(
@Query('id')
id
) {
const bean = await this.getService().info(id);
return this.ok(bean);
}
@Post('/update')
async update(
@Body(ALL)
bean
) {
await this.getService().update(bean);
return this.ok(null);
}
@Post('/delete')
async delete(
@Query('id')
id
) {
await this.getService().delete([id]);
return this.ok(null);
}
}
@@ -0,0 +1,11 @@
export class EnumItem {
value: string;
label: string;
color: string;
constructor(value, label, color) {
this.value = value;
this.label = label;
this.color = color;
}
}
@@ -0,0 +1,14 @@
import { Constants } from '../constants.js';
import { BaseException } from './base-exception.js';
/**
* 授权异常
*/
export class AuthException extends BaseException {
constructor(message) {
super(
'AuthException',
Constants.res.auth.code,
message ? message : Constants.res.auth.message
);
}
}
@@ -0,0 +1,11 @@
/**
* 异常基类
*/
export class BaseException extends Error {
status: number;
constructor(name, code, message) {
super(message);
this.name = name;
this.status = code;
}
}
@@ -0,0 +1,14 @@
import { Constants } from '../constants.js';
import { BaseException } from './base-exception.js';
/**
* 通用异常
*/
export class CommonException extends BaseException {
constructor(message) {
super(
'CommonException',
Constants.res.error.code,
message ? message : Constants.res.error.message
);
}
}
@@ -0,0 +1,7 @@
export * from './auth-exception.js'
export * from './base-exception.js'
export * from './permission-exception.js'
export * from './preview-exception.js'
export * from './validation-exception.js'
export * from './vip-exception.js'
export * from './common-exception.js'
@@ -0,0 +1,14 @@
import { Constants } from '../constants.js';
import { BaseException } from './base-exception.js';
/**
* 授权异常
*/
export class PermissionException extends BaseException {
constructor(message?: string) {
super(
'PermissionException',
Constants.res.permission.code,
message ? message : Constants.res.permission.message
);
}
}
@@ -0,0 +1,14 @@
import { Constants } from '../constants.js';
import { BaseException } from './base-exception.js';
/**
* 预览模式
*/
export class PreviewException extends BaseException {
constructor(message) {
super(
'PreviewException',
Constants.res.preview.code,
message ? message : Constants.res.preview.message
);
}
}
@@ -0,0 +1,14 @@
import { Constants } from '../constants.js';
import { BaseException } from './base-exception.js';
/**
* 校验异常
*/
export class ValidateException extends BaseException {
constructor(message) {
super(
'ValidateException',
Constants.res.validation.code,
message ? message : Constants.res.validation.message
);
}
}
@@ -0,0 +1,10 @@
import { Constants } from '../constants.js';
import { BaseException } from './base-exception.js';
/**
* 需要vip异常
*/
export class NeedVIPException extends BaseException {
constructor(message) {
super('NeedVIPException', Constants.res.needvip.code, message ? message : Constants.res.needvip.message);
}
}
@@ -0,0 +1,7 @@
export * from './base-controller.js';
export * from './constants.js';
export * from './crud-controller.js';
export * from './enum-item.js';
export * from './exception/index.js';
export * from './result.js';
export * from './base-service.js';
@@ -0,0 +1,18 @@
export class Result<T> {
code: number;
msg: string;
data: T;
constructor(code, msg, data?) {
this.code = code;
this.msg = msg;
this.data = data;
}
static error(code = 1, msg) {
return new Result(code, msg, null);
}
static success(msg, data?) {
return new Result(0, msg, data);
}
}