refactor: 确立独立子工程架构 (backend, admin, mpuniapp) 并同步更新 AGENTS.md 规范

这个提交包含在:
wikiboss
2026-09-20 17:05:22 +08:00
父节点 de3cf8b870
当前提交 9fa1d1fbd0
共有 1679 个文件被更改,包括 204798 次插入 和 16817 次删除

查看文件

@@ -0,0 +1,19 @@
import { ModuleConfig } from '@cool-midway/core';
/**
* 模块配置
*/
export default () => {
return {
// 模块名称
name: '数据回收',
// 模块描述
description: '收集被删除的数据,管理和恢复',
// 中间件,只对本模块有效
middlewares: [],
// 中间件,全局有效
globalMiddlewares: [],
// 模块加载顺序,默认为0,值越大越优先加载
order: 0,
} as ModuleConfig;
};

查看文件

@@ -0,0 +1,35 @@
import { BaseSysUserEntity } from './../../../base/entity/sys/user';
import { RecycleDataEntity } from './../../entity/data';
import { Body, Inject, Post, Provide } from '@midwayjs/core';
import { CoolController, BaseController } from '@cool-midway/core';
import { RecycleDataService } from '../../service/data';
/**
* 数据回收
*/
@Provide()
@CoolController({
api: ['info', 'page'],
entity: RecycleDataEntity,
pageQueryOp: {
keyWordLikeFields: ['b.name', 'a.url'],
select: ['a.*', 'b.name as userName'],
join: [
{
entity: BaseSysUserEntity,
alias: 'b',
condition: 'a.userId = b.id',
},
],
},
})
export class AdminRecycleDataController extends BaseController {
@Inject()
recycleDataService: RecycleDataService;
@Post('/restore', { summary: '恢复数据' })
async restore(@Body('ids') ids: number[]) {
await this.recycleDataService.restore(ids);
return this.ok();
}
}

查看文件

@@ -0,0 +1,41 @@
import { BaseEntity, transformerJson } from '../../base/entity/base';
import { Entity, Column, Index } from 'typeorm';
/**
* 数据回收站 软删除的时候数据会回收到该表
*/
@Entity('recycle_data')
export class RecycleDataEntity extends BaseEntity {
@Column({ comment: '表', type: 'json', transformer: transformerJson })
entityInfo: {
// 数据源名称
dataSourceName: string;
// entity
entity: string;
};
@Index()
@Column({ comment: '操作人', nullable: true })
userId: number;
@Column({
comment: '被删除的数据',
type: 'json',
transformer: transformerJson,
})
data: object[];
@Column({ comment: '请求的接口', nullable: true })
url: string;
@Column({
comment: '请求参数',
nullable: true,
type: 'json',
transformer: transformerJson,
})
params: string;
@Column({ comment: '删除数据条数', default: 1 })
count: number;
}

查看文件

@@ -0,0 +1,21 @@
import { CoolEvent, EVENT, Event } from '@cool-midway/core';
import { Inject } from '@midwayjs/core';
import { RecycleDataService } from '../service/data';
/**
* 接受数据事件
*/
@CoolEvent()
export class RecycleDataEvent {
@Inject()
recycleDataService: RecycleDataService;
/**
* 数据被删除
* @param params
*/
@Event(EVENT.SOFT_DELETE)
async softDelete(params) {
await this.recycleDataService.record(params);
}
}

查看文件

@@ -0,0 +1,32 @@
import {
Provide,
Inject,
CommonSchedule,
TaskLocal,
FORMAT,
} from '@midwayjs/core';
import { ILogger } from '@midwayjs/logger';
import { RecycleDataService } from '../service/data';
/**
* 数据定时清除定时任务
*/
@Provide()
export class BaseRecycleSchedule implements CommonSchedule {
@Inject()
recycleDataService: RecycleDataService;
@Inject()
logger: ILogger;
// 定时执行的具体任务
@TaskLocal(FORMAT.CRONTAB.EVERY_DAY)
async exec() {
this.logger.info('清除回收站数据定时任务开始执行');
const startTime = Date.now();
await this.recycleDataService.clear();
this.logger.info(
`清除回收站数据定时任务结束,耗时:${Date.now() - startTime}ms`
);
}
}

查看文件

@@ -0,0 +1,84 @@
import { RecycleDataEntity } from './../entity/data';
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel, TypeORMDataSourceManager } from '@midwayjs/typeorm';
import { LessThan, Repository } from 'typeorm';
import * as _ from 'lodash';
import * as moment from 'moment';
import { BaseSysConfService } from '../../base/service/sys/conf';
/**
* 数据回收
*/
@Provide()
@Scope(ScopeEnum.Request, { allowDowngrade: true })
export class RecycleDataService extends BaseService {
@InjectEntityModel(RecycleDataEntity)
recycleDataEntity: Repository<RecycleDataEntity>;
@Inject()
typeORMDataSourceManager: TypeORMDataSourceManager;
@Inject()
baseSysConfService: BaseSysConfService;
/**
* 恢复数据
* @param ids
*/
async restore(ids: number[]) {
for (const id of ids) {
const info = await this.recycleDataEntity.findOneBy({ id });
if (!info) {
continue;
}
let entityModel = this.typeORMDataSourceManager
.getDataSource(info.entityInfo.dataSourceName)
.getRepository(info.entityInfo.entity);
await entityModel.save(info.data);
await this.recycleDataEntity.delete(id);
}
}
/**
* 记录数据
* @param params
*/
async record(params) {
const { ctx, data, entity } = params;
if (!ctx?.req) return;
const dataSourceName =
this.typeORMDataSourceManager.getDataSourceNameByModel(entity.target);
const url = ctx?.url;
await this.recycleDataEntity.save({
entityInfo: {
dataSourceName,
entity: entity.target.name,
},
url,
params:
ctx?.req.method === 'GET' ? ctx?.request.query : ctx?.request.body,
data,
count: data.length,
userId: _.startsWith(url, '/admin/') ? ctx?.admin.userId : ctx?.user?.id,
});
}
/**
* 日志
* @param isAll 是否清除全部
*/
async clear(isAll?) {
if (isAll) {
await this.recycleDataEntity.clear();
return;
}
const keepDay = await this.baseSysConfService.getValue('recycleKeep');
if (keepDay) {
const beforeDate = moment().add(-keepDay, 'days').startOf('day').toDate();
await this.recycleDataEntity.delete({ createTime: LessThan(beforeDate) });
} else {
await this.recycleDataEntity.clear();
}
}
}