feat: divide the fields into general and system

This commit is contained in:
chenos 2021-08-07 23:14:14 +08:00
parent 2f880c6cd0
commit c34d82d180
9 changed files with 105 additions and 262 deletions

View File

@ -45,7 +45,7 @@ export default () => {
'x-component': 'Input',
'x-read-pretty': true,
},
fields: {
generalFields: {
type: 'array',
title: '数据表字段',
'x-decorator': 'FormItem',

View File

@ -23,7 +23,7 @@ export function useCollection(props: CollectionProviderProps) {
collection = collections.find((item) => item.name === collectionName);
}
if (collection) {
fields = collection?.fields || [];
fields = collection?.generalFields || [];
}
let sortableField = collection?.sortable;
if (collection?.sortable && typeof collection?.sortable === 'object') {

View File

@ -24,7 +24,8 @@ import {
Input,
Badge,
message,
Spin,
Drawer,
Space,
} from 'antd';
import { options, interfaces, getDefaultFields } from './interfaces';
import {
@ -127,11 +128,12 @@ export const DatabaseCollection = observer((props) => {
>
<DatabaseOutlined />
</Button>
<Modal
bodyStyle={{
overflow: 'auto',
maxHeight: 'calc(100vh - 300px)',
}}
<Drawer
width={'50%'}
// bodyStyle={{
// overflow: 'auto',
// maxHeight: 'calc(100vh - 300px)',
// }}
title={
<div style={{ textAlign: 'center' }}>
<DndContext
@ -249,21 +251,49 @@ export const DatabaseCollection = observer((props) => {
</div>
}
visible={visible}
onCancel={() => {
onClose={() => {
setVisible(false);
}}
okText={'保存'}
cancelText={'关闭'}
onOk={async () => {
footer={
<Space>
<Button
onClick={() => {
setVisible(false);
}}
>
</Button>
<Button
type={'primary'}
onClick={async () => {
try {
form.clearErrors();
await form.validate(`${field.address.entire}.${activeIndex}.*`);
await form.validate(
`${field.address.entire}.${activeIndex}.*`,
);
delete field.value[activeIndex]['unsaved'];
await createOrUpdateCollection(field.value[activeIndex]);
await refresh();
message.success('保存成功');
} catch (error) {}
}}
>
</Button>
</Space>
}
// okText={'保存'}
// cancelText={'关闭'}
// onOk={async () => {
// try {
// form.clearErrors();
// await form.validate(`${field.address.entire}.${activeIndex}.*`);
// delete field.value[activeIndex]['unsaved'];
// await createOrUpdateCollection(field.value[activeIndex]);
// await refresh();
// message.success('保存成功');
// } catch (error) {}
// }}
>
<FormLayout layout={'vertical'}>
<RecursionField
@ -279,7 +309,7 @@ export const DatabaseCollection = observer((props) => {
{(form) => <pre>{JSON.stringify(form.values, null, 2)}</pre>}
</FormConsumer> */}
</FormLayout>
</Modal>
</Drawer>
</div>
);
});

View File

@ -3,65 +3,27 @@ import { TableOptions } from '@nocobase/database';
export default {
name: 'action_changes',
title: '变动值',
developerMode: true,
internal: true,
createdBy: false,
updatedBy: false,
createdAt: false,
updatedAt: false,
logging: 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,
},
}
],
actions: [
{
type: 'list',
name: 'list',
title: '查看'
}
],
views_v2: [
{
type: 'table',
name: 'table',
fields: [
'field',
'before',
'after',
],
}
],
} as TableOptions;

View File

@ -4,217 +4,37 @@ import { LOG_TYPE_CREATE, LOG_TYPE_UPDATE, LOG_TYPE_DESTROY } from '../constants
export default {
name: 'action_logs',
title: '操作记录',
developerMode: true,
internal: true,
createdBy: false,
updatedBy: false,
updatedAt: false,
logging: false,
fields: [
{
interface: 'createdAt',
name: 'created_at',
type: 'date',
title: '操作时间',
showTime: true,
component: {
showInTable: true,
showInDetail: true,
},
name: 'created_at',
},
{
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: LOG_TYPE_CREATE, label: '新增', color: 'blue' },
{ value: LOG_TYPE_UPDATE, label: '更新', color: 'volcano' },
{ value: LOG_TYPE_DESTROY, label: '删除', color: 'magenta' },
],
component: {
showInTable: true,
showInDetail: true,
},
},
{
type: 'integer',
name: 'index',
title: '数据ID',
component: {
showInTable: true,
},
},
{
interface: 'subTable',
type: 'hasMany',
name: 'changes',
target: 'action_changes',
title: '数据变动',
component: {
showInDetail: true,
},
}
],
actions: [
{
type: 'filter',
name: 'filter',
title: '筛选'
},
{
type: 'list',
name: 'list',
title: '查看',
// sort: '-created_at'
},
],
views_v2: [
{
developerMode: true,
type: 'table',
name: 'table',
title: '全部数据',
labelField: 'created_at',
actions: [
{
name: 'filter',
type: 'filter',
title: '过滤',
},
],
fields: ['created_at', 'user', 'collection', 'type', 'index'],
detailsOpenMode: 'drawer', // window
details: ['descriptions'],
sort: ['-created_at'],
},
{
developerMode: true,
type: 'table',
name: 'create',
title: '新增数据',
labelField: 'created_at',
actions: [
{
name: 'filter',
type: 'filter',
title: '过滤',
},
],
fields: ['created_at', 'user', 'collection', 'type', 'index'],
detailsOpenMode: 'drawer', // window
details: ['descriptions'],
filter: {
and: [
{
type: 'create',
}
],
},
sort: ['-created_at'],
},
{
developerMode: true,
type: 'table',
name: 'update',
title: '更新数据',
labelField: 'created_at',
actions: [
{
name: 'filter',
type: 'filter',
title: '过滤',
},
],
fields: ['created_at', 'user', 'collection', 'type', 'index'],
detailsOpenMode: 'drawer', // window
details: ['descriptions'],
filter: {
and: [
{
type: 'update',
}
],
},
sort: ['-created_at'],
},
{
developerMode: true,
type: 'table',
name: 'destroy',
title: '删除数据',
labelField: 'created_at',
actions: [
{
name: 'filter',
type: 'filter',
title: '过滤',
},
],
fields: ['created_at', 'user', 'collection', 'type', 'index'],
detailsOpenMode: 'drawer', // window
details: ['descriptions'],
filter: {
and: [
{
type: 'destroy',
}
],
},
sort: ['-created_at'],
},
{
type: 'table',
name: 'table2',
title: '操作日志列表',
labelField: 'created_at',
actions: [
{
name: 'filter',
type: 'filter',
title: '过滤',
},
],
fields: ['created_at', 'user', 'type', 'index'],
detailsOpenMode: 'drawer', // window
details: ['descriptions'],
sort: ['-created_at'],
},
{
developerMode: true,
type: 'descriptions',
name: 'descriptions',
title: '详情',
fields: ['created_at', 'user', 'collection', 'type', 'index', 'changes'],
actions: [],
},
],
} as TableOptions;

View File

@ -12,7 +12,7 @@ export default async function() {
// 为所有的表都加上日志的 hooks
database.addHook('afterTableInit', (table) => {
if (table.options.logging === false) {
if (!table.options.logging) {
return;
}
addAll(database.getModel(table.options.name));
@ -20,7 +20,7 @@ export default async function() {
const Collection = database.getModel('collections');
Collection.addHook('afterCreate', async (model, options) => {
if (model.get('logging') === false) {
if (!model.get('logging')) {
return;
}
@ -28,20 +28,21 @@ export default async function() {
const exists = await model.countFields({
where: {
type: { [Op.iLike]: 'hasMany' },
dataType: { [Op.iLike]: 'hasMany' },
name: 'action_logs'
},
transaction
});
if (!exists) {
await model.createField({
await model.createSystemField({
interface: 'linkTo',
type: 'hasMany',
dataType: 'hasMany',
name: 'action_logs',
target: 'action_logs',
title: '数据动态',
foreignKey: 'index',
state: 0,
scope: {
collection_name: model.get('name')
},

View File

@ -6,16 +6,17 @@ export default {
model: 'Collection',
sortable: 'sort',
fields: [
// {
// type: 'sort',
// name: 'sort',
// },
{
type: 'uid',
name: 'name',
primaryKey: true,
prefix: 't_',
},
{
type: 'boolean',
name: 'logging',
defaultValue: true,
},
{
type: 'string',
name: 'title',
@ -38,8 +39,29 @@ export default {
{
type: 'hasMany',
name: 'fields',
target: 'fields',
sourceKey: 'name',
},
{
type: 'hasMany',
name: 'generalFields',
target: 'fields',
foreignKey: 'collection_name',
sourceKey: 'name',
scope: {
state: 1,
},
},
{
type: 'hasMany',
name: 'systemFields',
target: 'fields',
foreignKey: 'collection_name',
sourceKey: 'name',
scope: {
state: 0,
},
},
{
type: 'belongsTo',
name: 'uiSchema',

View File

@ -11,18 +11,11 @@ export default {
scope: ['parentKey'],
},
fields: [
// {
// type: 'sort',
// name: 'sort',
// scope: ['parentKey'],
// },
{
type: 'uid',
name: 'key',
primaryKey: true,
prefix: 'f_',
// autoIncrement: false,
// defaultValue: DataTypes.UUIDV4,
},
{
type: 'string',
@ -40,6 +33,11 @@ export default {
type: 'string',
name: 'privilege',
},
{
type: 'integer',
name: 'state',
default: 1,
},
{
type: 'hasMany',
name: 'children',

View File

@ -36,12 +36,22 @@ export class Collection extends Model {
const json = this.toJSON();
const data: any = _.omit(json, ['options', 'created_at', 'updated_at']);
const options = json['options'] || {};
const fields = await this.getNestedFields();
return { ...data, ...options, fields }
const generalFields = await this.getNestedFields({
where: {
state: 1,
}
});
const systemFields = await this.getNestedFields({
where: {
state: 0,
}
});
return { ...data, ...options, generalFields, systemFields }
}
async getNestedFields() {
async getNestedFields(options) {
const fields = await this.getFields({
...options,
order: [['sort', 'asc']],
});
const items = [];
@ -60,8 +70,8 @@ export class Collection extends Model {
*/
async loadTableOptions(opts: any = {}) {
const options = await this.toProps();
// console.log(JSON.stringify(options, null, 2));
const table = this.database.table(options);
const { generalFields = [], systemFields = [], ...others } = options;
const table = this.database.table({ ...others, fields: generalFields.concat(systemFields) });
return table;
}