diff --git a/packages/api/src/migrations/sync.ts b/packages/api/src/migrations/sync.ts
new file mode 100644
index 000000000..2a469dfb7
--- /dev/null
+++ b/packages/api/src/migrations/sync.ts
@@ -0,0 +1,11 @@
+import Database from '@nocobase/database';
+import api from '../app';
+
+(async () => {
+ await api.loadPlugins();
+ const database: Database = api.database;
+ await database.sync({
+ // tables: ['collections', 'fields', 'actions', 'views', 'tabs'],
+ });
+ await database.close();
+})();
diff --git a/packages/client/src/constate/Collections.ts b/packages/client/src/constate/Collections.ts
index 512e2c468..7d53b9e46 100644
--- a/packages/client/src/constate/Collections.ts
+++ b/packages/client/src/constate/Collections.ts
@@ -10,6 +10,12 @@ const [CollectionsProvider, useCollectionsContext] = constate(() => {
findCollection(name) {
return result?.data?.find((item) => item.name === name);
},
+ async loadCollections(field: any) {
+ return result?.data?.map((item: any) => ({
+ label: item.title,
+ value: item.name,
+ }));
+ },
getFieldsByCollection(collectionName) {
const collection = result?.data?.find((item) => item.name === collectionName);
return collection?.generalFields;
diff --git a/packages/client/src/schemas/add-new/index.tsx b/packages/client/src/schemas/add-new/index.tsx
index 6135815a0..ba0546845 100644
--- a/packages/client/src/schemas/add-new/index.tsx
+++ b/packages/client/src/schemas/add-new/index.tsx
@@ -1370,6 +1370,7 @@ AddNew.FormItem = observer((props: any) => {
const { schema, insertBefore, insertAfter, appendChild, deepRemove } =
useDesignable();
const path = useSchemaPath();
+ const { loadCollections } = useCollectionsContext();
const { collection, fields, refresh } = useCollectionContext();
const [visible, setVisible] = useState(false);
const displayed = useDisplayedMapContext();
@@ -1562,7 +1563,7 @@ AddNew.FormItem = observer((props: any) => {
const values = await FormDialog(`添加字段`, () => {
return (
-
+
);
}).open({
diff --git a/packages/client/src/schemas/table/index.tsx b/packages/client/src/schemas/table/index.tsx
index b5bd84b1a..f8ab0e596 100644
--- a/packages/client/src/schemas/table/index.tsx
+++ b/packages/client/src/schemas/table/index.tsx
@@ -405,6 +405,7 @@ const useTableColumns = () => {
function AddColumn() {
const [visible, setVisible] = useState(false);
const { appendChild, remove } = useDesignable();
+ const { loadCollections } = useCollectionsContext();
const { collection, fields, refresh } = useCollectionContext();
const displayed = useDisplayedMapContext();
const { service } = useTable();
@@ -592,7 +593,7 @@ function AddColumn() {
const values = await FormDialog(`添加字段`, () => {
return (
-
+
);
}).open({
diff --git a/packages/plugin-action-logs/src/server.ts b/packages/plugin-action-logs/src/server.ts
index 9f46c66f9..1dc8346d4 100644
--- a/packages/plugin-action-logs/src/server.ts
+++ b/packages/plugin-action-logs/src/server.ts
@@ -18,40 +18,40 @@ export default async function() {
addAll(database.getModel(table.options.name));
});
- const Collection = database.getModel('collections');
- Collection.addHook('afterCreate', async (model, options) => {
- if (!model.get('logging')) {
- return;
- }
+ // const Collection = database.getModel('collections');
+ // Collection.addHook('afterCreate', async (model, options) => {
+ // if (!model.get('logging')) {
+ // return;
+ // }
- const { transaction = await model.sequelize.transaction() } = options;
+ // const { transaction = await model.sequelize.transaction() } = options;
- const exists = await model.countFields({
- where: {
- dataType: { [Op.iLike]: 'hasMany' },
- name: 'action_logs'
- },
- transaction
- });
+ // 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 (!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();
- }
- });
+ // if (!options.transaction) {
+ // await transaction.commit();
+ // }
+ // });
}
diff --git a/packages/plugin-collections/src/actions/fields.ts b/packages/plugin-collections/src/actions/fields.ts
index 15c0b2c01..048b834b7 100644
--- a/packages/plugin-collections/src/actions/fields.ts
+++ b/packages/plugin-collections/src/actions/fields.ts
@@ -6,6 +6,7 @@ import { cloneDeep, omit } from 'lodash';
export const create = async (ctx: actions.Context, next: actions.Next) => {
await actions.common.create(ctx, async () => {});
const { associated } = ctx.action.params;
+ await ctx.body.generateReverseField();
await associated.migrate();
// console.log('associated.migrate');
await next();
diff --git a/packages/plugin-collections/src/actions/index.ts b/packages/plugin-collections/src/actions/index.ts
index 063005edb..f2b2fc893 100644
--- a/packages/plugin-collections/src/actions/index.ts
+++ b/packages/plugin-collections/src/actions/index.ts
@@ -38,6 +38,17 @@ export const createOrUpdate = async (ctx: actions.Context, next: actions.Next) =
})
}
await collection.updateAssociations(values);
+
+ const fields = await collection.getGeneralFields({
+ where: {
+ interface: 'linkTo',
+ }
+ });
+
+ for (const field of fields) {
+ await field.generateReverseField();
+ }
+
await collection.migrate();
} catch (error) {
// console.log('error.errors', error.errors)
diff --git a/packages/plugin-collections/src/collections/fields.ts b/packages/plugin-collections/src/collections/fields.ts
index 747860845..81bb8ce25 100644
--- a/packages/plugin-collections/src/collections/fields.ts
+++ b/packages/plugin-collections/src/collections/fields.ts
@@ -46,12 +46,18 @@ export default {
foreignKey: 'parentKey',
},
{
- interface: 'linkTo',
type: 'belongsTo',
name: 'collection',
target: 'collections',
targetKey: 'name',
},
+ {
+ type: 'belongsTo',
+ name: 'reverseField',
+ target: 'fields',
+ sourceKey: 'key',
+ foreignKey: 'reverseKey',
+ },
{
type: 'belongsTo',
name: 'uiSchema',
diff --git a/packages/plugin-collections/src/models/field.ts b/packages/plugin-collections/src/models/field.ts
index 793d24f53..e3f1d6fd0 100644
--- a/packages/plugin-collections/src/models/field.ts
+++ b/packages/plugin-collections/src/models/field.ts
@@ -48,4 +48,54 @@ export class Field extends Model {
}
return items;
}
+
+ async generateReverseField(opts: any = {}) {
+ const { migrate = true } = opts;
+ if (this.get('interface') !== 'linkTo') {
+ return;
+ }
+ if (this.get('reverseKey')) {
+ return;
+ }
+ const fieldCollection = await this.getCollection();
+ const options: any = this.get('options') || {};
+ const Collection = this.database.getModel('collections');
+ let collection = await Collection.findOne({
+ where: {
+ name: options.target,
+ },
+ });
+ if (!collection) {
+ return;
+ }
+ const reverseField = await collection.createField({
+ interface: 'linkTo',
+ dataType: 'belongsToMany',
+ through: options.through,
+ foreignKey: options.otherKey,
+ otherKey: options.foreignKey,
+ sourceKey: options.targetKey,
+ targetKey: options.sourceKey,
+ target: this.get('collection_name'),
+ reverseKey: this.get('key'),
+ });
+ await reverseField.updateAssociations({
+ uiSchema: {
+ type: 'array',
+ title: `${fieldCollection?.title}`,
+ 'x-component': 'Select.Drawer',
+ 'x-component-props': {
+ multiple: true,
+ },
+ 'x-decorator': 'FormItem',
+ 'x-designable-bar': 'Select.Drawer.DesignableBar',
+ }
+ });
+ await this.update({
+ reverseKey: reverseField.key,
+ });
+ if (migrate) {
+ await collection.migrate();
+ }
+ }
}
diff --git a/packages/plugin-collections/src/server.ts b/packages/plugin-collections/src/server.ts
index b20a8f5b5..08b1a7df2 100644
--- a/packages/plugin-collections/src/server.ts
+++ b/packages/plugin-collections/src/server.ts
@@ -1,6 +1,6 @@
import path from 'path';
import { Application } from '@nocobase/server';
-import { registerModels, Table } from '@nocobase/database';
+import { registerModels, Table, uid } from '@nocobase/database';
import * as models from './models';
import { createOrUpdate, findAll } from './actions';
import { create } from './actions/fields';
@@ -27,6 +27,7 @@ export default async function (this: Application, options = {}) {
}
});
Field.beforeUpdate(async (model) => {
+ console.log('beforeUpdate', model.key);
if (!model.get('collection_name') && model.get('parentKey')) {
const field = await Field.findByPk(model.get('parentKey'));
if (field) {
@@ -37,8 +38,8 @@ export default async function (this: Application, options = {}) {
}
}
});
- Field.afterCreate(async (model) => {
- console.log('afterCreate');
+ Field.afterCreate(async (model, options) => {
+ console.log('afterCreate', model.key, model.get('collection_name'));
if (model.get('interface') !== 'subTable') {
return;
}