Feature/action logs (#61)
* feat: add action logs plugin * feat: add afterUpdate/afterDestroy hooks for logs * 子表格细节改进 * fix: subtable * activity * bugfix Co-authored-by: mytharcher <mytharcher@gmail.com>
This commit is contained in:
parent
4ed21682ac
commit
1ea08e62b6
@ -4,6 +4,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "cd packages/app && npm start",
|
"start": "cd packages/app && npm start",
|
||||||
"db-migrate": "cd packages/app && npm run db-migrate",
|
"db-migrate": "cd packages/app && npm run db-migrate",
|
||||||
|
"start:app:server": "cd packages/app && nodemon",
|
||||||
"start-server": "yarn nodemon",
|
"start-server": "yarn nodemon",
|
||||||
"bootstrap": "lerna bootstrap --no-ci",
|
"bootstrap": "lerna bootstrap --no-ci",
|
||||||
"build": "npm run build-father-build && node packages/father-build/bin/father-build.js",
|
"build": "npm run build-father-build && node packages/father-build/bin/father-build.js",
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
"@nocobase/client": "^0.3.0-alpha.0",
|
"@nocobase/client": "^0.3.0-alpha.0",
|
||||||
"@nocobase/database": "^0.3.0-alpha.0",
|
"@nocobase/database": "^0.3.0-alpha.0",
|
||||||
"@nocobase/father-build": "^0.3.0-alpha.0",
|
"@nocobase/father-build": "^0.3.0-alpha.0",
|
||||||
|
"@nocobase/plugin-action-logs": "^0.3.0-alpha.0",
|
||||||
"@nocobase/plugin-collections": "^0.3.0-alpha.0",
|
"@nocobase/plugin-collections": "^0.3.0-alpha.0",
|
||||||
"@nocobase/plugin-pages": "^0.3.0-alpha.0",
|
"@nocobase/plugin-pages": "^0.3.0-alpha.0",
|
||||||
"@nocobase/server": "^0.3.0-alpha.0",
|
"@nocobase/server": "^0.3.0-alpha.0",
|
||||||
|
@ -62,6 +62,7 @@ api.resourcer.registerActionHandlers({...actions.common, ...actions.associate});
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
api.registerPlugin('plugin-collections', [path.resolve(__dirname, '../../../plugin-collections'), {}]);
|
api.registerPlugin('plugin-collections', [path.resolve(__dirname, '../../../plugin-collections'), {}]);
|
||||||
|
api.registerPlugin('plugin-action-logs', [path.resolve(__dirname, '../../../plugin-action-logs'), {}]);
|
||||||
api.registerPlugin('plugin-pages', [path.resolve(__dirname, '../../../plugin-pages'), {}]);
|
api.registerPlugin('plugin-pages', [path.resolve(__dirname, '../../../plugin-pages'), {}]);
|
||||||
api.registerPlugin('plugin-users', [path.resolve(__dirname, '../../../plugin-users'), {}]);
|
api.registerPlugin('plugin-users', [path.resolve(__dirname, '../../../plugin-users'), {}]);
|
||||||
api.registerPlugin('plugin-file-manager', [path.resolve(__dirname, '../../../plugin-file-manager'), {}]);
|
api.registerPlugin('plugin-file-manager', [path.resolve(__dirname, '../../../plugin-file-manager'), {}]);
|
||||||
|
42
packages/app/src/api/migrations/create-action-logs-table.ts
Normal file
42
packages/app/src/api/migrations/create-action-logs-table.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import api from '../app';
|
||||||
|
import Database from '@nocobase/database';
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
await api.loadPlugins();
|
||||||
|
const database: Database = api.database;
|
||||||
|
await api.database.sync({
|
||||||
|
tables: ['actions_scopes', 'action_logs', 'action_changes'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const [Collection, Page] = database.getModels(['collections', 'pages']);
|
||||||
|
|
||||||
|
const tables = database.getTables(['actions_scopes', 'action_logs', 'action_changes']);
|
||||||
|
|
||||||
|
for (let table of tables) {
|
||||||
|
console.log(table.getName());
|
||||||
|
await Collection.import(table.getOptions(), { update: true, migrate: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
await Page.import({
|
||||||
|
title: '动态',
|
||||||
|
type: 'layout',
|
||||||
|
path: '/activity',
|
||||||
|
icon: 'NotificationOutlined',
|
||||||
|
template: 'SideMenuLayout',
|
||||||
|
sort: 85,
|
||||||
|
showInMenu: true,
|
||||||
|
parent_id: 1,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: '操作记录',
|
||||||
|
type: 'collection',
|
||||||
|
path: '/activity/logs',
|
||||||
|
icon: 'HistoryOutlined',
|
||||||
|
template: 'collection',
|
||||||
|
collection: 'action_logs',
|
||||||
|
sort: 80,
|
||||||
|
showInMenu: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
})();
|
@ -74,6 +74,27 @@ const data = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '动态',
|
||||||
|
type: 'layout',
|
||||||
|
path: '/activity',
|
||||||
|
icon: 'NotificationOutlined',
|
||||||
|
template: 'SideMenuLayout',
|
||||||
|
sort: 85,
|
||||||
|
showInMenu: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
title: '操作记录',
|
||||||
|
type: 'collection',
|
||||||
|
path: '/activity/logs',
|
||||||
|
icon: 'HistoryOutlined',
|
||||||
|
template: 'collection',
|
||||||
|
collection: 'action_logs',
|
||||||
|
sort: 80,
|
||||||
|
showInMenu: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '配置',
|
title: '配置',
|
||||||
type: 'layout',
|
type: 'layout',
|
||||||
|
@ -8,6 +8,8 @@ import {
|
|||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
TableOutlined,
|
TableOutlined,
|
||||||
MenuOutlined,
|
MenuOutlined,
|
||||||
|
HistoryOutlined,
|
||||||
|
NotificationOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
export const IconFont = createFromIconfontCN({
|
export const IconFont = createFromIconfontCN({
|
||||||
@ -36,6 +38,7 @@ export function registerIcons(components) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerIcons({
|
registerIcons({
|
||||||
|
HistoryOutlined,
|
||||||
MenuOutlined,
|
MenuOutlined,
|
||||||
TableOutlined,
|
TableOutlined,
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
@ -43,6 +46,7 @@ registerIcons({
|
|||||||
UserOutlined,
|
UserOutlined,
|
||||||
DatabaseOutlined,
|
DatabaseOutlined,
|
||||||
DashboardOutlined,
|
DashboardOutlined,
|
||||||
|
NotificationOutlined,
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IconProps {
|
interface IconProps {
|
||||||
|
@ -361,6 +361,20 @@ export function AttachmentFieldItem(props: any) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function LogField(props) {
|
||||||
|
const { value = {} } = props;
|
||||||
|
return (
|
||||||
|
<div>{value.title||value.name}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function LogFieldValue(props) {
|
||||||
|
const { value, schema, data } = props;
|
||||||
|
return (
|
||||||
|
<div>{value}</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
registerFieldComponents({
|
registerFieldComponents({
|
||||||
string: StringField,
|
string: StringField,
|
||||||
textarea: TextareaField,
|
textarea: TextareaField,
|
||||||
@ -380,10 +394,12 @@ registerFieldComponents({
|
|||||||
subTable: SubTableField,
|
subTable: SubTableField,
|
||||||
linkTo: LinkToField,
|
linkTo: LinkToField,
|
||||||
attachment: AttachmentField,
|
attachment: AttachmentField,
|
||||||
|
'logs.field': LogField,
|
||||||
|
'logs.fieldValue': LogFieldValue,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function Field(props: any) {
|
export default function Field(props: any) {
|
||||||
const { schema = {} } = props;
|
const { schema = {} } = props;
|
||||||
const Component = getFieldComponent(schema.interface);
|
const Component = getFieldComponent(schema.interface||get(schema, 'component.type'));
|
||||||
return <Component {...props}/>;
|
return <Component {...props}/>;
|
||||||
}
|
}
|
||||||
|
10
packages/plugin-action-logs/package.json
Normal file
10
packages/plugin-action-logs/package.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "@nocobase/plugin-action-logs",
|
||||||
|
"version": "0.3.0-alpha.0",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nocobase/database": "^0.3.0-alpha.0",
|
||||||
|
"@nocobase/resourcer": "^0.3.0-alpha.0"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
import { TableOptions } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'action_changes',
|
||||||
|
title: '变动值',
|
||||||
|
developerMode: true,
|
||||||
|
internal: true,
|
||||||
|
createdBy: false,
|
||||||
|
updatedBy: false,
|
||||||
|
createdAt: false,
|
||||||
|
updatedAt: false,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
interface: 'linkTo',
|
||||||
|
type: 'belongsTo',
|
||||||
|
name: 'log',
|
||||||
|
target: 'action_logs',
|
||||||
|
title: '所属操作'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'jsonb',
|
||||||
|
name: 'field',
|
||||||
|
title: '字段信息',
|
||||||
|
component: {
|
||||||
|
type: 'logs.field',
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'jsonb',
|
||||||
|
name: 'before',
|
||||||
|
title: '操作前',
|
||||||
|
component: {
|
||||||
|
type: 'logs.fieldValue',
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'jsonb',
|
||||||
|
name: 'after',
|
||||||
|
title: '操作后',
|
||||||
|
component: {
|
||||||
|
type: 'logs.fieldValue',
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
views: [
|
||||||
|
{
|
||||||
|
type: 'table',
|
||||||
|
name: 'table',
|
||||||
|
title: '列表',
|
||||||
|
template: 'Table',
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as TableOptions;
|
108
packages/plugin-action-logs/src/collections/action_logs.ts
Normal file
108
packages/plugin-action-logs/src/collections/action_logs.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import { TableOptions } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'action_logs',
|
||||||
|
title: '操作记录',
|
||||||
|
developerMode: true,
|
||||||
|
internal: true,
|
||||||
|
createdBy: false,
|
||||||
|
updatedBy: false,
|
||||||
|
updatedAt: false,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
interface: 'createdAt',
|
||||||
|
name: 'created_at',
|
||||||
|
type: 'date',
|
||||||
|
title: '操作时间',
|
||||||
|
showTime: true,
|
||||||
|
component: {
|
||||||
|
showInTable: true,
|
||||||
|
showInDetail: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
interface: 'linkTo',
|
||||||
|
type: 'belongsTo',
|
||||||
|
name: 'user',
|
||||||
|
target: 'users',
|
||||||
|
title: '操作用户',
|
||||||
|
appends: true,
|
||||||
|
labelField: 'nickname',
|
||||||
|
component: {
|
||||||
|
showInTable: true,
|
||||||
|
showInDetail: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
interface: 'linkTo',
|
||||||
|
type: 'belongsTo',
|
||||||
|
name: 'collection',
|
||||||
|
target: 'collections',
|
||||||
|
title: '数据表',
|
||||||
|
targetKey: 'name',
|
||||||
|
appends: true,
|
||||||
|
labelField: 'title',
|
||||||
|
component: {
|
||||||
|
showInTable: true,
|
||||||
|
showInDetail: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
interface: 'select',
|
||||||
|
type: 'string',
|
||||||
|
name: 'type',
|
||||||
|
title: '操作类型',
|
||||||
|
filterable: true,
|
||||||
|
dataSource: [
|
||||||
|
{ value: 'create', label: '新增' },
|
||||||
|
{ value: 'update', label: '更新' },
|
||||||
|
{ value: 'destroy', label: '删除' },
|
||||||
|
],
|
||||||
|
component: {
|
||||||
|
showInTable: true,
|
||||||
|
showInDetail: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'integer',
|
||||||
|
name: 'index',
|
||||||
|
title: '对象索引',
|
||||||
|
component: {
|
||||||
|
showInTable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
interface: 'subTable',
|
||||||
|
type: 'hasMany',
|
||||||
|
name: 'changes',
|
||||||
|
target: 'action_changes',
|
||||||
|
title: '数据变动',
|
||||||
|
component: {
|
||||||
|
showInDetail: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
name: 'list',
|
||||||
|
title: '查看',
|
||||||
|
sort: '-created_at'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
views: [
|
||||||
|
{
|
||||||
|
type: 'table',
|
||||||
|
name: 'table',
|
||||||
|
title: '列表',
|
||||||
|
template: 'Table',
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'details',
|
||||||
|
name: 'details',
|
||||||
|
title: '详情',
|
||||||
|
template: 'Details',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as TableOptions;
|
54
packages/plugin-action-logs/src/hooks/after-create.ts
Normal file
54
packages/plugin-action-logs/src/hooks/after-create.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { Field } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default async function(model, options) {
|
||||||
|
if (!options.context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { database: db } = model;
|
||||||
|
const { context, transaction = await db.sequelize.transaction() } = options;
|
||||||
|
const {
|
||||||
|
state,
|
||||||
|
action: {
|
||||||
|
params: {
|
||||||
|
actionName,
|
||||||
|
resourceName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} = context;
|
||||||
|
const ActionLog = db.getModel('action_logs');
|
||||||
|
// 创建操作记录
|
||||||
|
const log = await ActionLog.create({
|
||||||
|
type: actionName,
|
||||||
|
collection_name: model.constructor.name,
|
||||||
|
index: model.get(model.constructor.primaryKeyAttribute),
|
||||||
|
created_at: model.get('created_at')
|
||||||
|
}, {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
|
||||||
|
const fields = db.getTable(model.constructor.name).getFields();
|
||||||
|
const fieldsList = Array.from(fields.values());
|
||||||
|
const changes = [];
|
||||||
|
model.changed().forEach((key: string) => {
|
||||||
|
const field = fields.get(key) || fieldsList.find((item: Field) => item.options.field === key);
|
||||||
|
if (field) {
|
||||||
|
changes.push({
|
||||||
|
field: field.options,
|
||||||
|
after: model.get(key)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// TODO(bug): state.currentUser 不是 belongsTo field 的 target 实例
|
||||||
|
// Sequelize 会另外创建一个 Model 的继承类,无法直传 instance
|
||||||
|
// await log.setUser(state.currentUser, { transaction });
|
||||||
|
await log.updateAssociations({
|
||||||
|
...(state.currentUser ? { user: state.currentUser.id } : {}),
|
||||||
|
changes
|
||||||
|
}, {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!options.transaction) {
|
||||||
|
await transaction.commit();
|
||||||
|
}
|
||||||
|
}
|
53
packages/plugin-action-logs/src/hooks/after-destroy.ts
Normal file
53
packages/plugin-action-logs/src/hooks/after-destroy.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { Field } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default async function(model, options) {
|
||||||
|
if (!options.context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { database: db } = model;
|
||||||
|
const { context, transaction = await db.sequelize.transaction() } = options;
|
||||||
|
const {
|
||||||
|
state,
|
||||||
|
action: {
|
||||||
|
params: {
|
||||||
|
actionName,
|
||||||
|
resourceName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} = context;
|
||||||
|
const ActionLog = db.getModel('action_logs');
|
||||||
|
// 创建操作记录
|
||||||
|
const log = await ActionLog.create({
|
||||||
|
// user_id: state.currentUser ? state.currentUser.id : null,
|
||||||
|
type: actionName,
|
||||||
|
collection_name: model.constructor.name,
|
||||||
|
index: model.get(model.constructor.primaryKeyAttribute),
|
||||||
|
// created_at: model.get('created_at')
|
||||||
|
}, {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
|
||||||
|
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({
|
||||||
|
...(state.currentUser ? { user: state.currentUser.id } : {}),
|
||||||
|
changes
|
||||||
|
}, {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!options.transaction) {
|
||||||
|
await transaction.commit();
|
||||||
|
}
|
||||||
|
}
|
59
packages/plugin-action-logs/src/hooks/after-update.ts
Normal file
59
packages/plugin-action-logs/src/hooks/after-update.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { Field } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default async function(model, options) {
|
||||||
|
if (!options.context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { database: db } = model;
|
||||||
|
const { context, transaction = await db.sequelize.transaction() } = options;
|
||||||
|
const {
|
||||||
|
state,
|
||||||
|
action: {
|
||||||
|
params: {
|
||||||
|
actionName,
|
||||||
|
resourceName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} = context;
|
||||||
|
const ActionLog = db.getModel('action_logs');
|
||||||
|
|
||||||
|
const fields = db.getTable(model.constructor.name).getFields();
|
||||||
|
const fieldsList = Array.from(fields.values());
|
||||||
|
const changes = [];
|
||||||
|
|
||||||
|
model.changed().forEach((key: string) => {
|
||||||
|
const field = fields.get(key) || fieldsList.find((item: Field) => item.options.field === key);
|
||||||
|
if (field && field.options.type !== 'formula') {
|
||||||
|
changes.push({
|
||||||
|
field: field.options,
|
||||||
|
after: model.get(key),
|
||||||
|
before: model.previous(key)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changes.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建操作记录
|
||||||
|
const log = await ActionLog.create({
|
||||||
|
type: actionName,
|
||||||
|
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 (!options.transaction) {
|
||||||
|
await transaction.commit();
|
||||||
|
}
|
||||||
|
}
|
10
packages/plugin-action-logs/src/hooks/index.ts
Normal file
10
packages/plugin-action-logs/src/hooks/index.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import afterCreate from './after-create';
|
||||||
|
import afterUpdate from './after-update';
|
||||||
|
import afterDestroy from './after-destroy';
|
||||||
|
|
||||||
|
export function addAll(Model) {
|
||||||
|
Model.addHook('afterCreate', afterCreate);
|
||||||
|
// Model.addHook('afterBulkCreate', hooks.afterBulkCreate);
|
||||||
|
Model.addHook('afterUpdate', afterUpdate);
|
||||||
|
Model.addHook('afterDestroy', afterDestroy);
|
||||||
|
}
|
20
packages/plugin-action-logs/src/server.ts
Normal file
20
packages/plugin-action-logs/src/server.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
import { addAll } from './hooks';
|
||||||
|
|
||||||
|
export default async function() {
|
||||||
|
const { database } = this;
|
||||||
|
|
||||||
|
database.import({
|
||||||
|
directory: path.resolve(__dirname, 'collections'),
|
||||||
|
});
|
||||||
|
|
||||||
|
// 为所有的表都加上日志的 hooks
|
||||||
|
database.addHook('afterTableInit', function (table) {
|
||||||
|
if (['action_logs', 'action_changes'].includes(table.options.name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const Model = database.getModel(table.options.name);
|
||||||
|
addAll(Model);
|
||||||
|
});
|
||||||
|
}
|
@ -157,6 +157,7 @@ const transforms = {
|
|||||||
return schema;
|
return schema;
|
||||||
},
|
},
|
||||||
details: async (fields: Model[], context?: any) => {
|
details: async (fields: Model[], context?: any) => {
|
||||||
|
const [Field] = context.db.getModels(['fields']) as ModelCtor<Model>[];
|
||||||
const arr = [];
|
const arr = [];
|
||||||
for (const field of fields) {
|
for (const field of fields) {
|
||||||
if (!get(field.component, 'showInDetail')) {
|
if (!get(field.component, 'showInDetail')) {
|
||||||
@ -167,10 +168,17 @@ const transforms = {
|
|||||||
}
|
}
|
||||||
const props = {};
|
const props = {};
|
||||||
if (field.get('interface') === 'subTable') {
|
if (field.get('interface') === 'subTable') {
|
||||||
const children = await field.getChildren({
|
const children = await Field.findAll(Field.parseApiJson({
|
||||||
order: [['sort', 'asc']],
|
filter: {
|
||||||
});
|
collection_name: field.get('target'),
|
||||||
props['children'] = children.map(child => ({...child.toJSON(), dataIndex: child.name.split('.')}))
|
},
|
||||||
|
perPage: -1,
|
||||||
|
sort: ['sort'],
|
||||||
|
}));
|
||||||
|
// const children = await field.getChildren({
|
||||||
|
// order: [['sort', 'asc']],
|
||||||
|
// });
|
||||||
|
props['children'] = children.filter(item => item.get('component.showInTable')).map(child => ({...child.toJSON(), dataIndex: child.name.split('.')}))
|
||||||
}
|
}
|
||||||
arr.push({
|
arr.push({
|
||||||
...field.toJSON(),
|
...field.toJSON(),
|
||||||
|
@ -35,7 +35,6 @@ export class Permissions {
|
|||||||
});
|
});
|
||||||
|
|
||||||
database.getModel('collections').addHook('afterCreate', async (model: any, options) => {
|
database.getModel('collections').addHook('afterCreate', async (model: any, options) => {
|
||||||
// console.log('plugin-permissions hook');
|
|
||||||
await model.updateAssociations({
|
await model.updateAssociations({
|
||||||
scopes: [
|
scopes: [
|
||||||
{
|
{
|
||||||
|
@ -18,10 +18,6 @@ export default async function (options = {}) {
|
|||||||
|
|
||||||
registerFields(fields);
|
registerFields(fields);
|
||||||
|
|
||||||
database.import({
|
|
||||||
directory: path.resolve(__dirname, 'collections'),
|
|
||||||
});
|
|
||||||
|
|
||||||
database.addHook('afterTableInit', (table) => {
|
database.addHook('afterTableInit', (table) => {
|
||||||
let { createdBy, updatedBy, internal } = table.getOptions();
|
let { createdBy, updatedBy, internal } = table.getOptions();
|
||||||
// 非内置表,默认创建 createdBy 和 updatedBy
|
// 非内置表,默认创建 createdBy 和 updatedBy
|
||||||
@ -39,6 +35,10 @@ export default async function (options = {}) {
|
|||||||
.map(type => table.addField(makeOptions(type, fieldsToMake[type])));
|
.map(type => table.addField(makeOptions(type, fieldsToMake[type])));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
database.import({
|
||||||
|
directory: path.resolve(__dirname, 'collections'),
|
||||||
|
});
|
||||||
|
|
||||||
resourcer.registerActionHandlers({
|
resourcer.registerActionHandlers({
|
||||||
'users:login': login,
|
'users:login': login,
|
||||||
'users:register': register,
|
'users:register': register,
|
||||||
|
Loading…
Reference in New Issue
Block a user