tachybase_todo/packages/plugin-collections/src/models/collection.ts

252 lines
6.5 KiB
TypeScript
Raw Normal View History

import _ from 'lodash';
import BaseModel from './base';
2020-12-21 10:42:44 +08:00
import Field from './field';
import { TableOptions } from '@nocobase/database';
2020-12-08 09:59:41 +08:00
import { SaveOptions, Op } from 'sequelize';
/**
*
*
* 使 3+2
* 1. id
* 2.
* 3.
* 4.
* 5.
*
* @param title
*/
export function generateCollectionName(title?: string): string {
return `t_${Date.now().toString(36)}_${Math.random().toString(36).replace('0.', '').slice(-4).padStart(4, '0')}`;
}
2020-10-24 15:34:43 +08:00
2020-12-08 09:59:41 +08:00
export interface LoadOptions {
reset?: boolean;
where?: any;
2020-12-23 20:29:11 +08:00
skipExisting?: boolean;
2020-12-08 09:59:41 +08:00
[key: string]: any;
}
export interface MigrateOptions {
[key: string]: any;
}
export class CollectionModel extends BaseModel {
generateName() {
this.set('name', generateCollectionName());
}
/**
* name collection
*
* @param name
*/
static async findByName(name: string) {
return this.findOne({ where: { name } });
}
2020-12-08 09:59:41 +08:00
/**
* DOTO
* - database.table
* -
*
* @param opts
*/
async loadTableOptions(opts: any = {}) {
const options = await this.getOptions();
const prevTable = this.database.getTable(this.get('name'));
const prevOptions = prevTable ? prevTable.getOptions() : {};
// table 是初始化和重新初始化
2020-12-08 09:59:41 +08:00
const table = this.database.table({...prevOptions, ...options});
// 如果关系表未加载,一起处理
2020-12-23 20:29:11 +08:00
// const associationTableNames = [];
// for (const [key, association] of table.getAssociations()) {
// // TODO是否需要考虑重载的情况暂时是跳过处理
// if (!this.database.isDefined(association.options.target)) {
// continue;
// }
// associationTableNames.push(association.options.target);
// }
// console.log({associationTableNames});
// if (associationTableNames.length) {
// await CollectionModel.load({
// ...opts,
// where: {
// name: {
// [Op.in]: associationTableNames,
// }
// }
// });
// }
2020-12-08 09:59:41 +08:00
return table;
}
/**
*
*/
2020-12-08 09:59:41 +08:00
async migrate(options: MigrateOptions = {}) {
const { isNewRecord } = options;
const table = await this.loadTableOptions(options);
// 如果不是新增数据force 必须为 false
if (!isNewRecord) {
return await table.sync({
force: false,
alter: {
drop: false,
}
});
}
// TODO: 暂时加了个 collectionSync 解决 collection.create 的数据不清空问题
// @ts-ignore
const sync = this.sequelize.options.collectionSync;
return await table.sync(sync || {
force: false,
alter: {
drop: false,
}
});
}
async getFieldsOptions() {
const fieldsOptions = [];
const fields = await this.getFields();
for (const field of fields) {
fieldsOptions.push(await field.getOptions());
2020-10-24 15:34:43 +08:00
}
return fieldsOptions;
}
async getOptions(): Promise<TableOptions> {
return {
...this.get(),
fields: await this.getFieldsOptions(),
};
}
2020-12-08 09:59:41 +08:00
/**
* TODO
*
* @param options
*/
static async load(options: LoadOptions = {}) {
2020-12-23 20:29:11 +08:00
const { skipExisting = false, reset = false, where = {}, transaction } = options;
2020-12-08 09:59:41 +08:00
const collections = await this.findAll({
transaction,
2020-12-08 09:59:41 +08:00
where,
});
for (const collection of collections) {
2020-12-23 20:29:11 +08:00
if (skipExisting && this.database.isDefined(collection.get('name'))) {
continue;
}
2020-12-08 09:59:41 +08:00
await collection.loadTableOptions({
transaction,
2020-12-08 09:59:41 +08:00
reset,
});
}
}
static async import(data: TableOptions, options: SaveOptions = {}): Promise<CollectionModel> {
data = _.cloneDeep(data);
// @ts-ignore
const { update } = options;
let collection: CollectionModel;
if (data.name) {
collection = await this.findOne({
...options,
where: {
name: data.name,
},
});
} else if (data.title) {
collection = await this.findOne({
...options,
where: {
title: data.title,
},
});
}
if (collection && update) {
await collection.update(data, options);
}
if (!collection) {
collection = await this.create(data, options);
}
const associations = ['fields', 'tabs', 'actions', 'views'];
for (const key of associations) {
if (!Array.isArray(data[key])) {
continue;
}
const Model = this.database.getModel(key);
2020-12-21 10:42:44 +08:00
let ids = [];
2020-12-25 16:15:58 +08:00
const View = this.database.getModel('views');
2020-12-16 20:47:10 +08:00
for (const index in data[key]) {
2020-12-21 10:42:44 +08:00
if (key === 'fields') {
ids = await Field.import(data[key], {
...options,
collectionName: collection.name,
});
continue;
}
let model;
2020-12-16 20:47:10 +08:00
const item = data[key][index];
if (item.name) {
model = await Model.findOne({
...options,
where: {
collection_name: collection.name,
name: item.name,
},
});
} else if (item.title) {
model = await Model.findOne({
...options,
where: {
collection_name: collection.name,
title: item.title,
},
});
}
if (model && update) {
2020-12-16 20:47:10 +08:00
await model.update({...item, sort: index+1}, options);
}
if (!model) {
model = await Model.create({
...item,
2020-12-16 20:47:10 +08:00
sort: index+1,
collection_name: collection.name,
}, options);
}
if (model) {
2020-12-25 16:15:58 +08:00
if (key === 'tabs') {
let associationField;
if (item.association) {
associationField = await Field.findOne({
where: {
name: item.association,
collection_name: collection.name,
},
});
// TODO: tabs 表还未创建,暂时先这么处理
if (associationField) {
await model.updateAssociations({
associationField: associationField.id,
});
}
2020-12-25 16:15:58 +08:00
}
}
ids.push(model.id);
}
}
2021-01-10 09:40:29 +08:00
if (ids.length && collection.get('internal')) {
await collection.updateAssociations({
[key]: ids,
});
}
}
return collection;
2020-10-24 15:34:43 +08:00
}
}
export default CollectionModel;