diff --git a/package.json b/package.json index af31ab9..fba36bf 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ }, "scripts": { "start": "NODE_ENV=production node ./bootstrap.js", - "dev": "rimraf src/index.ts && cool check entity && cross-env NODE_ENV=local mwtsc --cleanOutDir --watch --run @midwayjs/mock/app.js", + "dev": "rimraf src/index.ts && cool check entity --clear && cross-env NODE_ENV=local mwtsc --cleanOutDir --watch --run @midwayjs/mock/app.js", "test": "cross-env NODE_ENV=unittest jest", "cov": "jest --coverage", "lint": "mwts check", diff --git a/src/entities.ts b/src/entities.ts index d8028b0..5b2a4bd 100644 --- a/src/entities.ts +++ b/src/entities.ts @@ -1,25 +1,2 @@ // 自动生成的文件,请勿手动修改 -import * as entity0 from './modules/plugin/entity/info'; -import * as entity1 from './modules/base/entity/sys/user_role'; -import * as entity2 from './modules/base/entity/sys/user'; -import * as entity3 from './modules/base/entity/sys/role_menu'; -import * as entity4 from './modules/base/entity/sys/role_department'; -import * as entity5 from './modules/base/entity/sys/role'; -import * as entity6 from './modules/base/entity/sys/param'; -import * as entity7 from './modules/base/entity/sys/menu'; -import * as entity8 from './modules/base/entity/sys/log'; -import * as entity9 from './modules/base/entity/sys/department'; -import * as entity10 from './modules/base/entity/sys/conf'; -export const entities = [ - ...Object.values(entity0), - ...Object.values(entity1), - ...Object.values(entity2), - ...Object.values(entity3), - ...Object.values(entity4), - ...Object.values(entity5), - ...Object.values(entity6), - ...Object.values(entity7), - ...Object.values(entity8), - ...Object.values(entity9), - ...Object.values(entity10), -]; +export const entities = []; diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index c405fde..0000000 --- a/src/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** This file generated by @midwayjs/bundle-helper */ - export { MainConfiguration as Configuration } from './configuration'; -export * from './comm/utils'; -export * from './config/config.default'; -export * from './config/config.local'; -export * from './modules/plugin/entity/info'; -export * from './modules/base/entity/sys/user_role'; -export * from './modules/base/entity/sys/user'; -export * from './modules/base/entity/sys/role_menu'; -export * from './modules/base/entity/sys/role_department'; -export * from './modules/base/entity/sys/role'; -export * from './modules/base/entity/sys/param'; -export * from './modules/base/entity/sys/menu'; -export * from './modules/base/entity/sys/log'; -export * from './modules/base/entity/sys/department'; -export * from './modules/base/entity/sys/conf'; -export * from './entities'; -export * from './config/config.prod'; -export * from './interface'; -export * from './modules/base/service/sys/conf'; -export * from './modules/base/service/sys/log'; -export * from './modules/base/middleware/log'; -export * from './modules/base/middleware/authority'; -export * from './modules/base/config'; -export * from './modules/plugin/interface'; -export * from './modules/plugin/service/center'; -export * from './modules/plugin/event/init'; -export * from './modules/plugin/service/types'; -export * from './modules/plugin/service/info'; -export * from './modules/base/dto/login'; -export * from './modules/base/service/sys/data'; -export * from './modules/base/service/sys/menu'; -export * from './modules/base/service/sys/department'; -export * from './modules/base/service/sys/perms'; -export * from './modules/base/service/sys/role'; -export * from './modules/base/service/sys/login'; -export * from './modules/base/service/sys/user'; -export * from './modules/base/controller/admin/comm'; -export * from './modules/base/service/sys/param'; -export * from './modules/base/controller/admin/open'; -export * from './modules/base/controller/admin/sys/department'; -export * from './modules/base/controller/admin/sys/log'; -export * from './modules/base/controller/admin/sys/menu'; -export * from './modules/base/controller/admin/sys/param'; -export * from './modules/base/controller/admin/sys/role'; -export * from './modules/base/controller/admin/sys/user'; -export * from './modules/base/controller/app/comm'; -export * from './modules/base/event/menu'; -export * from './modules/base/job/log'; -export * from './modules/plugin/config'; -export * from './modules/plugin/controller/admin/info'; -export * from './modules/plugin/event/app'; -export * from './modules/plugin/hooks/base'; -export * from './modules/plugin/hooks/upload/interface'; -export * from './modules/plugin/hooks/upload/index'; diff --git a/src/modules/dict/config.ts b/src/modules/dict/config.ts new file mode 100644 index 0000000..0c7e579 --- /dev/null +++ b/src/modules/dict/config.ts @@ -0,0 +1,19 @@ +import { ModuleConfig } from '@cool-midway/core'; + +/** + * 模块配置 + */ +export default () => { + return { + // 模块名称 + name: '字典管理', + // 模块描述 + description: '数据字典等', + // 中间件,只对本模块有效 + middlewares: [], + // 中间件,全局有效 + globalMiddlewares: [], + // 模块加载顺序,默认为0,值越大越优先加载 + order: 0, + } as ModuleConfig; +}; diff --git a/src/modules/dict/controller/admin/info.ts b/src/modules/dict/controller/admin/info.ts new file mode 100644 index 0000000..d61edec --- /dev/null +++ b/src/modules/dict/controller/admin/info.ts @@ -0,0 +1,30 @@ +import { DictInfoEntity } from './../../entity/info'; +import { Body, Inject, Post, Provide } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { DictInfoService } from '../../service/info'; + +/** + * 字典信息 + */ +@Provide() +@CoolController({ + api: ['add', 'delete', 'update', 'info', 'list', 'page'], + entity: DictInfoEntity, + service: DictInfoService, + listQueryOp: { + fieldEq: ['typeId'], + keyWordLikeFields: ['name'], + addOrderBy: { + createTime: 'ASC', + }, + }, +}) +export class AdminDictInfoController extends BaseController { + @Inject() + dictInfoService: DictInfoService; + + @Post('/data', { summary: '获得字典数据' }) + async data(@Body('types') types: string[] = []) { + return this.ok(await this.dictInfoService.data(types)); + } +} diff --git a/src/modules/dict/controller/admin/type.ts b/src/modules/dict/controller/admin/type.ts new file mode 100644 index 0000000..1118eac --- /dev/null +++ b/src/modules/dict/controller/admin/type.ts @@ -0,0 +1,18 @@ +import { DictTypeEntity } from './../../entity/type'; +import { Provide } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { DictTypeService } from '../../service/type'; + +/** + * 字典类型 + */ +@Provide() +@CoolController({ + api: ['add', 'delete', 'update', 'info', 'list', 'page'], + entity: DictTypeEntity, + service: DictTypeService, + listQueryOp: { + keyWordLikeFields: ['name'], + }, +}) +export class AdminDictTypeController extends BaseController {} diff --git a/src/modules/dict/controller/app/info.ts b/src/modules/dict/controller/app/info.ts new file mode 100644 index 0000000..ab82da2 --- /dev/null +++ b/src/modules/dict/controller/app/info.ts @@ -0,0 +1,26 @@ +import { Body, Inject, Post, Provide } from '@midwayjs/core'; +import { + CoolController, + BaseController, + CoolUrlTag, + TagTypes, + CoolTag, +} from '@cool-midway/core'; +import { DictInfoService } from '../../service/info'; + +/** + * 字典信息 + */ +@Provide() +@CoolController() +@CoolUrlTag() +export class AppDictInfoController extends BaseController { + @Inject() + dictInfoService: DictInfoService; + + @CoolTag(TagTypes.IGNORE_TOKEN) + @Post('/data', { summary: '获得字典数据' }) + async data(@Body('types') types: string[] = []) { + return this.ok(await this.dictInfoService.data(types)); + } +} diff --git a/src/modules/dict/db.json b/src/modules/dict/db.json new file mode 100644 index 0000000..31c79a2 --- /dev/null +++ b/src/modules/dict/db.json @@ -0,0 +1,88 @@ +{ + "dict_info": [ + { + "id": 21, + "typeId": 19, + "name": "COOL", + "orderNum": 1, + "remark": null, + "parentId": null, + "value": "cool" + }, + { + "id": 22, + "typeId": 19, + "name": "闪酷", + "orderNum": 2, + "remark": null, + "parentId": null, + "value": "https://show.cool-admin.com/api/public/uploads/20230308/c731b0cba84046268b10edbbcf36f948_315c243a448e1369fa145c5ea3f020da.gif" + }, + { + "id": 23, + "typeId": 20, + "name": "法师", + "orderNum": 1, + "remark": null, + "parentId": null, + "value": "4" + }, + { + "id": 24, + "typeId": 20, + "name": "战士", + "orderNum": 2, + "remark": null, + "parentId": null, + "value": "3" + }, + { + "id": 25, + "typeId": 20, + "name": "坦克", + "orderNum": 3, + "remark": null, + "parentId": null, + "value": "2" + }, + { + "id": 26, + "typeId": 20, + "name": "刺客", + "orderNum": 4, + "remark": null, + "parentId": null, + "value": "1" + }, + { + "id": 27, + "typeId": 20, + "name": "射手", + "orderNum": 5, + "remark": null, + "parentId": null, + "value": "0" + }, + { + "id": 30, + "typeId": 20, + "name": "幻影刺客", + "orderNum": 1, + "remark": null, + "parentId": 26, + "value": "5" + } + ], + "dict_type": [ + { + "id": 19, + "name": "品牌", + "key": "brand" + }, + { + "id": 20, + "name": "职业", + "key": "occupation" + } + ] +} \ No newline at end of file diff --git a/src/modules/dict/entity/info.ts b/src/modules/dict/entity/info.ts new file mode 100644 index 0000000..68d4701 --- /dev/null +++ b/src/modules/dict/entity/info.ts @@ -0,0 +1,26 @@ +import { BaseEntity } from '@cool-midway/core'; +import { Column, Entity } from 'typeorm'; + +/** + * 字典信息 + */ +@Entity('dict_info') +export class DictInfoEntity extends BaseEntity { + @Column({ comment: '类型ID' }) + typeId: number; + + @Column({ comment: '名称' }) + name: string; + + @Column({ comment: '值', nullable: true }) + value: string; + + @Column({ comment: '排序', default: 0 }) + orderNum: number; + + @Column({ comment: '备注', nullable: true }) + remark: string; + + @Column({ comment: '父ID', default: null }) + parentId: number; +} diff --git a/src/modules/dict/entity/type.ts b/src/modules/dict/entity/type.ts new file mode 100644 index 0000000..1b5d1b4 --- /dev/null +++ b/src/modules/dict/entity/type.ts @@ -0,0 +1,14 @@ +import { BaseEntity } from '@cool-midway/core'; +import { Column, Entity } from 'typeorm'; + +/** + * 字典类别 + */ +@Entity('dict_type') +export class DictTypeEntity extends BaseEntity { + @Column({ comment: '名称' }) + name: string; + + @Column({ comment: '标识' }) + key: string; +} diff --git a/src/modules/dict/service/info.ts b/src/modules/dict/service/info.ts new file mode 100644 index 0000000..e6f4db9 --- /dev/null +++ b/src/modules/dict/service/info.ts @@ -0,0 +1,137 @@ +import { DictTypeEntity } from './../entity/type'; +import { DictInfoEntity } from './../entity/info'; +import { Config, Provide } from '@midwayjs/core'; +import { BaseService } from '@cool-midway/core'; +import { InjectEntityModel } from '@midwayjs/typeorm'; +import { Repository, In } from 'typeorm'; +import * as _ from 'lodash'; + +/** + * 字典信息 + */ +@Provide() +export class DictInfoService extends BaseService { + @InjectEntityModel(DictInfoEntity) + dictInfoEntity: Repository; + + @InjectEntityModel(DictTypeEntity) + dictTypeEntity: Repository; + + @Config('typeorm.dataSource.default.type') + ormType: string; + + /** + * 获得字典数据 + * @param types + */ + async data(types: string[]) { + const result = {}; + let typeData = await this.dictTypeEntity.find(); + if (!_.isEmpty(types)) { + typeData = await this.dictTypeEntity.findBy({ key: In(types) }); + } + if (_.isEmpty(typeData)) { + return {}; + } + const data = await this.dictInfoEntity + .createQueryBuilder('a') + .select([ + 'a.id', + 'a.name', + 'a.typeId', + 'a.parentId', + 'a.orderNum', + 'a.value', + ]) + .where('a.typeId in(:...typeIds)', { + typeIds: typeData.map(e => { + return e.id; + }), + }) + .orderBy('a.orderNum', 'ASC') + .addOrderBy('a.createTime', 'ASC') + .getMany(); + for (const item of typeData) { + result[item.key] = _.filter(data, { typeId: item.id }).map(e => { + const value = e.value ? Number(e.value) : e.value; + return { + ...e, + value: isNaN(value) ? e.value : value, + }; + }); + } + return result; + } + + /** + * 获得单个或多个字典值 + * @param value 字典值或字典值数组 + * @param key 字典类型 + * @returns + */ + async getValues(value: string | string[], key: string) { + // 获取字典类型 + const type = await this.dictTypeEntity.findOneBy({ key }); + if (!type) { + return null; // 或者适当的错误处理 + } + + // 根据typeId获取所有相关的字典信息 + const dictValues = await this.dictInfoEntity.find({ + where: { typeId: type.id }, + }); + + // 如果value是字符串,直接查找 + if (typeof value === 'string') { + return this.findValueInDictValues(value, dictValues); + } + + // 如果value是数组,遍历数组,对每个元素进行查找 + return value.map(val => this.findValueInDictValues(val, dictValues)); + } + + /** + * 在字典值数组中查找指定的值 + * @param value 要查找的值 + * @param dictValues 字典值数组 + * @returns + */ + findValueInDictValues(value: string, dictValues: any[]) { + let result = dictValues.find(dictValue => dictValue.value === value); + if (!result) { + result = dictValues.find(dictValue => dictValue.id === parseInt(value)); + } + return result ? result.name : null; // 或者适当的错误处理 + } + + /** + * 修改之后 + * @param data + * @param type + */ + async modifyAfter(data: any, type: 'delete' | 'update' | 'add') { + if (type === 'delete') { + for (const id of data) { + await this.delChildDict(id); + } + } + } + + /** + * 删除子字典 + * @param id + */ + private async delChildDict(id) { + const delDict = await this.dictInfoEntity.findBy({ parentId: id }); + if (_.isEmpty(delDict)) { + return; + } + const delDictIds = delDict.map(e => { + return e.id; + }); + await this.dictInfoEntity.delete(delDictIds); + for (const dictId of delDictIds) { + await this.delChildDict(dictId); + } + } +} diff --git a/src/modules/dict/service/type.ts b/src/modules/dict/service/type.ts new file mode 100644 index 0000000..86283f3 --- /dev/null +++ b/src/modules/dict/service/type.ts @@ -0,0 +1,25 @@ +import { DictInfoEntity } from './../entity/info'; +import { Provide } from '@midwayjs/core'; +import { BaseService } from '@cool-midway/core'; +import { InjectEntityModel } from '@midwayjs/typeorm'; +import { Repository, In } from 'typeorm'; + +/** + * 描述 + */ +@Provide() +export class DictTypeService extends BaseService { + @InjectEntityModel(DictInfoEntity) + dictInfoEntity: Repository; + + /** + * 删除 + * @param ids + */ + async delete(ids) { + super.delete(ids); + await this.dictInfoEntity.delete({ + typeId: In(ids), + }); + } +} diff --git a/src/modules/recycle/config.ts b/src/modules/recycle/config.ts new file mode 100644 index 0000000..3421900 --- /dev/null +++ b/src/modules/recycle/config.ts @@ -0,0 +1,19 @@ +import { ModuleConfig } from '@cool-midway/core'; + +/** + * 模块配置 + */ +export default () => { + return { + // 模块名称 + name: '数据回收', + // 模块描述 + description: '收集被删除的数据,管理和恢复', + // 中间件,只对本模块有效 + middlewares: [], + // 中间件,全局有效 + globalMiddlewares: [], + // 模块加载顺序,默认为0,值越大越优先加载 + order: 0, + } as ModuleConfig; +}; diff --git a/src/modules/recycle/controller/admin/data.ts b/src/modules/recycle/controller/admin/data.ts new file mode 100644 index 0000000..211f1f8 --- /dev/null +++ b/src/modules/recycle/controller/admin/data.ts @@ -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(); + } +} diff --git a/src/modules/recycle/entity/data.ts b/src/modules/recycle/entity/data.ts new file mode 100644 index 0000000..e150f43 --- /dev/null +++ b/src/modules/recycle/entity/data.ts @@ -0,0 +1,32 @@ +import { BaseEntity } from '@cool-midway/core'; +import { Entity, Column, Index } from 'typeorm'; + +/** + * 数据回收站 软删除的时候数据会回收到该表 + */ +@Entity('recycle_data') +export class RecycleDataEntity extends BaseEntity { + @Column({ comment: '表', type: 'json' }) + entityInfo: { + // 数据源名称 + dataSourceName: string; + // entity + entity: string; + }; + + @Index() + @Column({ comment: '操作人', nullable: true }) + userId: number; + + @Column({ comment: '被删除的数据', type: 'json' }) + data: object[]; + + @Column({ comment: '请求的接口', nullable: true }) + url: string; + + @Column({ comment: '请求参数', nullable: true, type: 'json' }) + params: string; + + @Column({ comment: '删除数据条数', default: 1 }) + count: number; +} diff --git a/src/modules/recycle/event/data.ts b/src/modules/recycle/event/data.ts new file mode 100644 index 0000000..5c96bab --- /dev/null +++ b/src/modules/recycle/event/data.ts @@ -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); + } +} diff --git a/src/modules/recycle/schedule/data.ts b/src/modules/recycle/schedule/data.ts new file mode 100644 index 0000000..f3f50b8 --- /dev/null +++ b/src/modules/recycle/schedule/data.ts @@ -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` + ); + } +} diff --git a/src/modules/recycle/service/data.ts b/src/modules/recycle/service/data.ts new file mode 100644 index 0000000..4b38838 --- /dev/null +++ b/src/modules/recycle/service/data.ts @@ -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; + + @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(); + } + } +} diff --git a/src/modules/space/config.ts b/src/modules/space/config.ts new file mode 100644 index 0000000..10e7cff --- /dev/null +++ b/src/modules/space/config.ts @@ -0,0 +1,24 @@ +import { ModuleConfig } from '@cool-midway/core'; + +/** + * 模块配置 + */ +export default () => { + return { + // 模块名称 + name: '文件空间', + // 模块描述 + description: '上传和管理文件资源', + // 中间件,只对本模块有效 + middlewares: [], + // 中间件,全局有效 + globalMiddlewares: [], + // 模块加载顺序,默认为0,值越大越优先加载 + order: 0, + // wps的配置 + wps: { + // 这是个测试的appId,会有水印 + appId: 'SX20230111NDUAGQ', + }, + } as ModuleConfig; +}; diff --git a/src/modules/space/controller/admin/info.ts b/src/modules/space/controller/admin/info.ts new file mode 100644 index 0000000..0aea9b7 --- /dev/null +++ b/src/modules/space/controller/admin/info.ts @@ -0,0 +1,18 @@ +import { Provide } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { SpaceInfoEntity } from '../../entity/info'; +import { SpaceInfoService } from '../../service/info'; + +/** + * 图片空间信息 + */ +@Provide() +@CoolController({ + api: ['add', 'delete', 'update', 'info', 'list', 'page'], + entity: SpaceInfoEntity, + service: SpaceInfoService, + pageQueryOp: { + fieldEq: ['type', 'classifyId'], + }, +}) +export class BaseAppSpaceInfoController extends BaseController {} diff --git a/src/modules/space/controller/admin/type.ts b/src/modules/space/controller/admin/type.ts new file mode 100644 index 0000000..a5e9cf7 --- /dev/null +++ b/src/modules/space/controller/admin/type.ts @@ -0,0 +1,15 @@ +import { Provide } from '@midwayjs/core'; +import { CoolController, BaseController } from '@cool-midway/core'; +import { SpaceTypeEntity } from '../../entity/type'; +import { SpaceTypeService } from '../../service/type'; + +/** + * 空间分类 + */ +@Provide() +@CoolController({ + api: ['add', 'delete', 'update', 'info', 'list', 'page'], + entity: SpaceTypeEntity, + service: SpaceTypeService, +}) +export class BaseAppSpaceTypeController extends BaseController {} diff --git a/src/modules/space/controller/说明.md b/src/modules/space/controller/说明.md new file mode 100644 index 0000000..440a373 --- /dev/null +++ b/src/modules/space/controller/说明.md @@ -0,0 +1 @@ +编写接口 \ No newline at end of file diff --git a/src/modules/space/entity/info.ts b/src/modules/space/entity/info.ts new file mode 100644 index 0000000..3c2d4fc --- /dev/null +++ b/src/modules/space/entity/info.ts @@ -0,0 +1,33 @@ +import { BaseEntity } from '@cool-midway/core'; +import { Column, Index, Entity } from 'typeorm'; + +/** + * 文件空间信息 + */ +@Entity('space_info') +export class SpaceInfoEntity extends BaseEntity { + @Column({ comment: '地址' }) + url: string; + + @Column({ comment: '类型' }) + type: string; + + @Column({ comment: '分类ID', nullable: true }) + classifyId: number; + + @Index() + @Column({ comment: '文件id' }) + fileId: string; + + @Column({ comment: '文件名' }) + name: string; + + @Column({ comment: '文件大小' }) + size: number; + + @Column({ comment: '文档版本', default: 1 }) + version: number; + + @Column({ comment: '文件位置' }) + key: string; +} diff --git a/src/modules/space/entity/type.ts b/src/modules/space/entity/type.ts new file mode 100644 index 0000000..15c4308 --- /dev/null +++ b/src/modules/space/entity/type.ts @@ -0,0 +1,14 @@ +import { BaseEntity } from '@cool-midway/core'; +import { Column, Entity } from 'typeorm'; + +/** + * 图片空间信息分类 + */ +@Entity('space_type') +export class SpaceTypeEntity extends BaseEntity { + @Column({ comment: '类别名称' }) + name: string; + + @Column({ comment: '父分类ID', nullable: true }) + parentId: number; +} diff --git a/src/modules/space/service/info.ts b/src/modules/space/service/info.ts new file mode 100644 index 0000000..cd3b0c5 --- /dev/null +++ b/src/modules/space/service/info.ts @@ -0,0 +1,30 @@ +import { SpaceInfoEntity } from './../entity/info'; +import { Inject, Provide } from '@midwayjs/core'; +import { BaseService, MODETYPE } from '@cool-midway/core'; +import { InjectEntityModel } from '@midwayjs/typeorm'; +import { Repository } from 'typeorm'; +import { PluginService } from '../../plugin/service/info'; + +/** + * 文件信息 + */ +@Provide() +export class SpaceInfoService extends BaseService { + @InjectEntityModel(SpaceInfoEntity) + spaceInfoEntity: Repository; + + @Inject() + pluginService: PluginService; + + /** + * 新增 + */ + async add(param) { + const result = await this.pluginService.invoke('upload', 'getMode'); + const config = await this.pluginService.getConfig('upload'); + if (result.mode == MODETYPE.LOCAL) { + param.key = param.url.replace(config.domain, ''); + } + return super.add(param); + } +} diff --git a/src/modules/space/service/type.ts b/src/modules/space/service/type.ts new file mode 100644 index 0000000..84b60f3 --- /dev/null +++ b/src/modules/space/service/type.ts @@ -0,0 +1,28 @@ +import { Provide } from '@midwayjs/core'; +import { BaseService } from '@cool-midway/core'; +import { InjectEntityModel } from '@midwayjs/typeorm'; +import { In, Repository } from 'typeorm'; +import { SpaceTypeEntity } from '../entity/type'; +import { SpaceInfoEntity } from '../entity/info'; + +/** + * 文件分类 + */ +@Provide() +export class SpaceTypeService extends BaseService { + @InjectEntityModel(SpaceTypeEntity) + spaceTypeEntity: Repository; + + @InjectEntityModel(SpaceInfoEntity) + spaceInfoEntity: Repository; + + /** + * 删除 + * @param ids + */ + async delete(ids: any) { + await super.delete(ids); + // 删除该分类下的文件信息 + await this.spaceInfoEntity.delete({ classifyId: In(ids) }); + } +}