feat: update action logs plugin
This commit is contained in:
parent
c182c29161
commit
e8113f3809
@ -168,7 +168,7 @@ type HookType =
|
|||||||
const hookType = this._getHookType(event);
|
const hookType = this._getHookType(event);
|
||||||
if (hookType) {
|
if (hookType) {
|
||||||
const state = this.hookTypes.get(hookType);
|
const state = this.hookTypes.get(hookType);
|
||||||
console.log('sequelize.addHook', hookType)
|
console.log('sequelize.addHook', event, hookType)
|
||||||
this.sequelize.addHook(hookType, async (...args: any[]) => {
|
this.sequelize.addHook(hookType, async (...args: any[]) => {
|
||||||
let modelName: string;
|
let modelName: string;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -182,7 +182,7 @@ type HookType =
|
|||||||
modelName = args?.[0]?.model?.name;
|
modelName = args?.[0]?.model?.name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
console.log({ modelName, args });
|
// console.log({ modelName, args });
|
||||||
if (modelName) {
|
if (modelName) {
|
||||||
await this.emitAsync(`${modelName}.${hookType}`, ...args);
|
await this.emitAsync(`${modelName}.${hookType}`, ...args);
|
||||||
}
|
}
|
||||||
|
@ -1,69 +1,66 @@
|
|||||||
|
import Database from '@nocobase/database';
|
||||||
|
import Application from '@nocobase/server';
|
||||||
import { getApp, getAPI, getAgent } from '.';
|
import { getApp, getAPI, getAgent } from '.';
|
||||||
|
|
||||||
describe('hook', () => {
|
describe('hook', () => {
|
||||||
let app;
|
let app: Application;
|
||||||
let anonymousAPI;
|
let db: Database;
|
||||||
let userAPI;
|
let api;
|
||||||
let db;
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
app = await getApp();
|
app = await getApp();
|
||||||
db = app.database;
|
db = app.database;
|
||||||
|
db.table({
|
||||||
anonymousAPI = getAPI(getAgent(app));
|
name: 'posts',
|
||||||
|
logging: true,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'title',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
name: 'status',
|
||||||
|
defaultValue: 'draft',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
await db.sync();
|
||||||
const User = db.getModel('users');
|
const User = db.getModel('users');
|
||||||
user = await User.create({ nickname: 'a', token: 'token1' });
|
const user = await User.create({ nickname: 'a', token: 'token1' });
|
||||||
|
console.log('beforeEach', user);
|
||||||
const userAgent = getAgent(app);
|
const userAgent = getAgent(app);
|
||||||
userAgent.set('Authorization', `Bearer ${user.token}`);
|
userAgent.set('Authorization', `Bearer ${user.token}`);
|
||||||
userAPI = getAPI(userAgent);
|
api = getAPI(userAgent);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => db.close());
|
afterEach(async () => {
|
||||||
|
await db.close();
|
||||||
|
});
|
||||||
|
|
||||||
describe('common', () => {
|
it('database', async () => {
|
||||||
it('create log', async () => {
|
const Post = db.getModel('posts');
|
||||||
await userAPI.resource('posts').create({
|
const post = await Post.create({ title: 't1' });
|
||||||
values: { title: 't1' }
|
await post.update({title: 't2'});
|
||||||
});
|
await post.destroy();
|
||||||
|
const ActionLog = db.getModel('action_logs');
|
||||||
|
const count = await ActionLog.count();
|
||||||
|
expect(count).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
const Post = db.getModel('posts');
|
it('resource', async () => {
|
||||||
const p1 = await Post.findByPk(1);
|
const response = await api.resource('posts').create({
|
||||||
|
values: { title: 't1' },
|
||||||
const logs = await p1.getAction_logs();
|
|
||||||
|
|
||||||
expect(logs.length).toBe(1);
|
|
||||||
expect(logs[0].get()).toMatchObject({
|
|
||||||
type: 'create',
|
|
||||||
index: p1.id,
|
|
||||||
user_id: user.id,
|
|
||||||
collection_name: 'posts'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
await api.resource('posts').update({
|
||||||
it('logs should be scoped (no other model logs)', async () => {
|
resourceKey: response.body.data.id,
|
||||||
await userAPI.resource('posts').create({
|
values: { title: 't2' },
|
||||||
values: { title: 't1' }
|
|
||||||
});
|
|
||||||
await userAPI.resource('posts').update({
|
|
||||||
resourceKey: '1',
|
|
||||||
values: { title: 't11' }
|
|
||||||
});
|
|
||||||
await userAPI.resource('posts').create({
|
|
||||||
values: { title: 't2' }
|
|
||||||
});
|
|
||||||
await userAPI.resource('comments').create({
|
|
||||||
values: { content: 'c1' }
|
|
||||||
});
|
|
||||||
|
|
||||||
const Post = db.getModel('posts');
|
|
||||||
const p1 = await Post.findByPk(1);
|
|
||||||
|
|
||||||
const logs = await p1.getAction_logs();
|
|
||||||
expect(logs.length).toBe(2);
|
|
||||||
expect(logs.map(item => item.collection_name)).toEqual(['posts', 'posts']);
|
|
||||||
});
|
});
|
||||||
|
await api.resource('posts').destroy({
|
||||||
|
resourceKey: response.body.data.id,
|
||||||
|
});
|
||||||
|
const ActionLog = db.getModel('action_logs');
|
||||||
|
const count = await ActionLog.count();
|
||||||
|
expect(count).toBe(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -45,43 +45,20 @@ export function getDatabase() {
|
|||||||
return new Database(config);
|
return new Database(config);
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getApp() {
|
export async function getApp(): Promise<Application> {
|
||||||
const app = new Application({
|
const app = new Application({
|
||||||
database: config,
|
database: config,
|
||||||
resourcer: {
|
resourcer: {
|
||||||
prefix: '/api',
|
prefix: '/api',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
app.resourcer.use(middlewares.associated);
|
|
||||||
app.resourcer.registerActionHandlers({ ...actions.associate, ...actions.common });
|
|
||||||
app.registerPlugin({
|
app.registerPlugin({
|
||||||
collections: path.resolve(__dirname, '../../../plugin-collections'),
|
collections: path.resolve(__dirname, '../../../plugin-collections'),
|
||||||
users: path.resolve(__dirname, '../../../plugin-users'),
|
users: path.resolve(__dirname, '../../../plugin-users'),
|
||||||
logs: plugin
|
logs: plugin
|
||||||
});
|
});
|
||||||
await app.loadPlugins();
|
await app.loadPlugins();
|
||||||
const testTables = app.database.import({
|
await app.database.sync();
|
||||||
directory: path.resolve(__dirname, './tables')
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
await app.database.sync();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const table of testTables.values()) {
|
|
||||||
// TODO(bug): 由于每个用例结束后不会清理用于测试的数据表,导致再次创建和更新
|
|
||||||
// 创建和更新里面仍会再次创建 fields,导致创建相关的数据重复,数据库报错。
|
|
||||||
await app.database.getModel('collections').import(table.getOptions(), { update: true, migrate: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
app.context.db = app.database;
|
|
||||||
app.use(bodyParser());
|
|
||||||
app.use(middleware({
|
|
||||||
prefix: '/api',
|
|
||||||
resourcer: app.resourcer,
|
|
||||||
database: app.database,
|
|
||||||
}));
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ export default {
|
|||||||
type: 'belongsTo',
|
type: 'belongsTo',
|
||||||
name: 'log',
|
name: 'log',
|
||||||
target: 'action_logs',
|
target: 'action_logs',
|
||||||
|
foreignKey: 'log_id',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'jsonb',
|
type: 'jsonb',
|
||||||
|
@ -22,6 +22,7 @@ export default {
|
|||||||
name: 'collection',
|
name: 'collection',
|
||||||
target: 'collections',
|
target: 'collections',
|
||||||
targetKey: 'name',
|
targetKey: 'name',
|
||||||
|
constraints: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'string',
|
type: 'string',
|
||||||
@ -35,6 +36,7 @@ export default {
|
|||||||
type: 'hasMany',
|
type: 'hasMany',
|
||||||
name: 'changes',
|
name: 'changes',
|
||||||
target: 'action_changes',
|
target: 'action_changes',
|
||||||
|
foreignKey: 'log_id',
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
} as TableOptions;
|
} as TableOptions;
|
||||||
|
@ -1,53 +1,52 @@
|
|||||||
import { Field } from '@nocobase/database';
|
import Database, { Field, Model } from '@nocobase/database';
|
||||||
import { LOG_TYPE_CREATE } from '../constants';
|
import { LOG_TYPE_CREATE } from '../constants';
|
||||||
|
|
||||||
export default async function (model, options) {
|
export async function afterCreate(model, options) {
|
||||||
if (!options.context) {
|
const db = model.database as Database;
|
||||||
|
const table = db.getTable(model.constructor.name);
|
||||||
|
if (!table.getOptions('logging')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { database: db } = model;
|
const { transaction = await db.sequelize.transaction() } = options;
|
||||||
const { context: { state }, transaction = await db.sequelize.transaction() } = options;
|
|
||||||
const ActionLog = db.getModel('action_logs');
|
const ActionLog = db.getModel('action_logs');
|
||||||
// 创建操作记录
|
const currentUserId = options?.context?.state?.currentUser?.id;
|
||||||
const log = await ActionLog.create({
|
try {
|
||||||
type: LOG_TYPE_CREATE,
|
const log = await ActionLog.create({
|
||||||
collection_name: model.constructor.name,
|
type: LOG_TYPE_CREATE,
|
||||||
index: model.get(model.constructor.primaryKeyAttribute),
|
collection_name: model.constructor.name,
|
||||||
created_at: model.get('created_at')
|
index: model.get(model.constructor.primaryKeyAttribute),
|
||||||
}, {
|
created_at: model.get('created_at'),
|
||||||
transaction
|
user_id: currentUserId,
|
||||||
});
|
|
||||||
if (state.currentUser) {
|
|
||||||
// TODO(bug): state.currentUser 不是 belongsTo field 的 target 实例
|
|
||||||
// Sequelize 会另外创建一个 Model 的继承类,直传 instance 因为无法匹配类会当做 id 造成类型错误
|
|
||||||
// await log.setUser(state.currentUser, { transaction });
|
|
||||||
await log.updateAssociations({ user: state.currentUser.id }, {
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const fields = db.getTable(model.constructor.name).getFields();
|
|
||||||
const fieldsList = Array.from(fields.values());
|
|
||||||
const changes = [];
|
|
||||||
const changed = model.changed();
|
|
||||||
if (changed) {
|
|
||||||
changed.forEach((key: string) => {
|
|
||||||
const field = fields.get(key) || fieldsList.find((item: Field) => item.options.field === key);
|
|
||||||
if (field && !field.options.hidden && field.options.type !== 'formula') {
|
|
||||||
changes.push({
|
|
||||||
field: field.options,
|
|
||||||
after: model.get(key)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await log.updateAssociations({
|
|
||||||
changes
|
|
||||||
}, {
|
}, {
|
||||||
transaction
|
transaction,
|
||||||
|
hooks: false,
|
||||||
});
|
});
|
||||||
}
|
const fields = db.getTable(model.constructor.name).getFields();
|
||||||
|
const fieldsList = Array.from(fields.values());
|
||||||
if (!options.transaction) {
|
const changes = [];
|
||||||
await transaction.commit();
|
const changed = model.changed();
|
||||||
|
if (changed) {
|
||||||
|
changed.forEach((key: string) => {
|
||||||
|
const field = fields.get(key) || fieldsList.find((item: Field) => item.options.field === key);
|
||||||
|
if (field && !field.options.hidden && field.options.type !== 'formula') {
|
||||||
|
changes.push({
|
||||||
|
field: field.options,
|
||||||
|
after: model.get(key)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await log.updateAssociations({
|
||||||
|
changes
|
||||||
|
}, {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!options.transaction) {
|
||||||
|
await transaction.commit();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (!options.transaction) {
|
||||||
|
await transaction.rollback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,48 @@
|
|||||||
import { Field } from '@nocobase/database';
|
import Database, { Field } from '@nocobase/database';
|
||||||
import { LOG_TYPE_DESTROY } from '../constants';
|
import { LOG_TYPE_DESTROY } from '../constants';
|
||||||
|
|
||||||
export default async function (model, options) {
|
export async function afterDestroy(model, options) {
|
||||||
if (!options.context) {
|
const db = model.database as Database;
|
||||||
|
const table = db.getTable(model.constructor.name);
|
||||||
|
if (!table.getOptions('logging')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { database: db } = model;
|
const { transaction = await db.sequelize.transaction() } = options;
|
||||||
const { context: { state }, transaction = await db.sequelize.transaction() } = options;
|
|
||||||
const ActionLog = db.getModel('action_logs');
|
const ActionLog = db.getModel('action_logs');
|
||||||
// 创建操作记录
|
const currentUserId = options?.context?.state?.currentUser?.id;
|
||||||
const log = await ActionLog.create({
|
try {
|
||||||
// user_id: state.currentUser ? state.currentUser.id : null,
|
const log = await ActionLog.create({
|
||||||
type: LOG_TYPE_DESTROY,
|
type: LOG_TYPE_DESTROY,
|
||||||
collection_name: model.constructor.name,
|
collection_name: model.constructor.name,
|
||||||
index: model.get(model.constructor.primaryKeyAttribute),
|
index: model.get(model.constructor.primaryKeyAttribute),
|
||||||
// created_at: model.get('created_at')
|
user_id: currentUserId,
|
||||||
}, {
|
}, {
|
||||||
transaction
|
transaction,
|
||||||
});
|
hooks: false,
|
||||||
if (state.currentUser) {
|
});
|
||||||
await log.updateAssociations({ user: state.currentUser.id }, {
|
const fields = db.getTable(model.constructor.name).getFields();
|
||||||
|
const fieldsList = Array.from(fields.values());
|
||||||
|
const changes = [];
|
||||||
|
Object.keys(model.get()).forEach((key: string) => {
|
||||||
|
const field = fields.get(key) || fieldsList.find((item: Field) => item.options.field === key);
|
||||||
|
if (field) {
|
||||||
|
changes.push({
|
||||||
|
field: field.options,
|
||||||
|
before: model.get(key)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await log.updateAssociations({
|
||||||
|
changes
|
||||||
|
}, {
|
||||||
transaction
|
transaction
|
||||||
});
|
});
|
||||||
}
|
if (!options.transaction) {
|
||||||
|
await transaction.commit();
|
||||||
const fields = db.getTable(model.constructor.name).getFields();
|
}
|
||||||
const fieldsList = Array.from(fields.values());
|
} catch (error) {
|
||||||
const changes = [];
|
if (!options.transaction) {
|
||||||
Object.keys(model.get()).forEach((key: string) => {
|
await transaction.rollback();
|
||||||
const field = fields.get(key) || fieldsList.find((item: Field) => item.options.field === key);
|
|
||||||
if (field) {
|
|
||||||
changes.push({
|
|
||||||
field: field.options,
|
|
||||||
before: model.get(key)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
await log.updateAssociations({
|
|
||||||
changes
|
|
||||||
}, {
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!options.transaction) {
|
|
||||||
await transaction.commit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,51 +1,57 @@
|
|||||||
import { Field } from '@nocobase/database';
|
import Database, { Field } from '@nocobase/database';
|
||||||
import { LOG_TYPE_UPDATE } from '../constants';
|
import { LOG_TYPE_UPDATE } from '../constants';
|
||||||
|
|
||||||
export default async function (model, options) {
|
export async function afterUpdate(model, options) {
|
||||||
if (!options.context) {
|
const db = model.database as Database;
|
||||||
|
const table = db.getTable(model.constructor.name);
|
||||||
|
if (!table.getOptions('logging')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { database: db } = model;
|
const changed = model.changed();
|
||||||
const { context: { state }, transaction = await db.sequelize.transaction() } = options;
|
if (!changed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { transaction = await db.sequelize.transaction() } = options;
|
||||||
const ActionLog = db.getModel('action_logs');
|
const ActionLog = db.getModel('action_logs');
|
||||||
|
const currentUserId = options?.context?.state?.currentUser?.id;
|
||||||
const fields = db.getTable(model.constructor.name).getFields();
|
const fields = db.getTable(model.constructor.name).getFields();
|
||||||
const fieldsList = Array.from(fields.values());
|
const fieldsList = Array.from(fields.values());
|
||||||
const changes = [];
|
const changes = [];
|
||||||
const changed = model.changed();
|
changed.forEach((key: string) => {
|
||||||
if (changed) {
|
const field = fields.get(key) || fieldsList.find((item: Field) => item.options.field === key);
|
||||||
changed.forEach((key: string) => {
|
if (field && !field.options.hidden && field.options.type !== 'formula') {
|
||||||
const field = fields.get(key) || fieldsList.find((item: Field) => item.options.field === key);
|
changes.push({
|
||||||
if (field && !field.options.hidden && field.options.type !== 'formula') {
|
field: field.options,
|
||||||
changes.push({
|
after: model.get(key),
|
||||||
field: field.options,
|
before: model.previous(key)
|
||||||
after: model.get(key),
|
|
||||||
before: model.previous(key)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (changes.length) {
|
|
||||||
// 创建操作记录
|
|
||||||
const log = await ActionLog.create({
|
|
||||||
type: LOG_TYPE_UPDATE,
|
|
||||||
collection_name: model.constructor.name,
|
|
||||||
index: model.get(model.constructor.primaryKeyAttribute),
|
|
||||||
created_at: model.get('updated_at')
|
|
||||||
}, {
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
await log.updateAssociations({
|
|
||||||
...(state.currentUser ? { user: state.currentUser.id } : {}),
|
|
||||||
changes
|
|
||||||
}, {
|
|
||||||
transaction
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
if (!changes.length) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
if (!options.transaction) {
|
const log = await ActionLog.create({
|
||||||
await transaction.commit();
|
type: LOG_TYPE_UPDATE,
|
||||||
|
collection_name: model.constructor.name,
|
||||||
|
index: model.get(model.constructor.primaryKeyAttribute),
|
||||||
|
created_at: model.get('updated_at'),
|
||||||
|
user_id: currentUserId,
|
||||||
|
}, {
|
||||||
|
transaction,
|
||||||
|
hooks: false,
|
||||||
|
});
|
||||||
|
await log.updateAssociations({
|
||||||
|
changes
|
||||||
|
}, {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
if (!options.transaction) {
|
||||||
|
await transaction.commit();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (!options.transaction) {
|
||||||
|
await transaction.rollback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
import afterCreate from './after-create';
|
export * from './after-create';
|
||||||
import afterUpdate from './after-update';
|
export * from './after-update';
|
||||||
import afterDestroy from './after-destroy';
|
export * from './after-destroy';
|
||||||
|
|
||||||
export function addAll(Model) {
|
|
||||||
Model.addHook('afterCreate', afterCreate);
|
|
||||||
// Model.addHook('afterBulkCreate', hooks.afterBulkCreate);
|
|
||||||
Model.addHook('afterUpdate', afterUpdate);
|
|
||||||
Model.addHook('afterDestroy', afterDestroy);
|
|
||||||
}
|
|
||||||
|
@ -1,57 +1,13 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { Op } from 'sequelize';
|
import Application from '@nocobase/server';
|
||||||
|
import { afterCreate, afterUpdate, afterDestroy } from './hooks';
|
||||||
|
|
||||||
import { addAll } from './hooks';
|
export default async function (this: Application) {
|
||||||
|
|
||||||
export default async function() {
|
|
||||||
const { database } = this;
|
const { database } = this;
|
||||||
|
|
||||||
database.import({
|
database.import({
|
||||||
directory: path.resolve(__dirname, 'collections'),
|
directory: path.resolve(__dirname, 'collections'),
|
||||||
});
|
});
|
||||||
|
database.on('afterCreate', afterCreate);
|
||||||
// 为所有的表都加上日志的 hooks
|
database.on('afterUpdate', afterUpdate);
|
||||||
database.addHook('afterTableInit', (table) => {
|
database.on('afterDestroy', afterDestroy);
|
||||||
if (!table.options.logging) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addAll(database.getModel(table.options.name));
|
|
||||||
});
|
|
||||||
|
|
||||||
// const Collection = database.getModel('collections');
|
|
||||||
// Collection.addHook('afterCreate', async (model, options) => {
|
|
||||||
// if (!model.get('logging')) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const { transaction = await model.sequelize.transaction() } = options;
|
|
||||||
|
|
||||||
// const exists = await model.countFields({
|
|
||||||
// where: {
|
|
||||||
// dataType: { [Op.iLike]: 'hasMany' },
|
|
||||||
// name: 'action_logs'
|
|
||||||
// },
|
|
||||||
// transaction
|
|
||||||
// });
|
|
||||||
|
|
||||||
// if (!exists) {
|
|
||||||
// await model.createSystemField({
|
|
||||||
// interface: 'linkTo',
|
|
||||||
// dataType: 'hasMany',
|
|
||||||
// name: 'action_logs',
|
|
||||||
// target: 'action_logs',
|
|
||||||
// title: '数据动态',
|
|
||||||
// foreignKey: 'index',
|
|
||||||
// state: 0,
|
|
||||||
// scope: {
|
|
||||||
// collection_name: model.get('name')
|
|
||||||
// },
|
|
||||||
// constraints: false
|
|
||||||
// }, { transaction });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!options.transaction) {
|
|
||||||
// await transaction.commit();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user