mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 07:06:06 +00:00
feat: improve collection hooks/fields/actions/views... (#30)
* feat: add onFinish callback * fix: update json attribute unsaved after query * refactor: collection hooks * feat: add migrate options
This commit is contained in:
parent
1980464f63
commit
3e3cb416b6
@ -166,7 +166,7 @@ const data = {
|
|||||||
const tables = database.getTables([]);
|
const tables = database.getTables([]);
|
||||||
|
|
||||||
for (let table of tables) {
|
for (let table of tables) {
|
||||||
await Collection.import(table.getOptions(), { hooks: false });
|
await Collection.import(table.getOptions(), { migrate: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
const Page = database.getModel('pages');
|
const Page = database.getModel('pages');
|
||||||
|
@ -5,15 +5,15 @@ import ViewFactory from '@/components/views';
|
|||||||
export function Create(props) {
|
export function Create(props) {
|
||||||
console.log(props);
|
console.log(props);
|
||||||
const { title, viewName, collection_name } = props.schema;
|
const { title, viewName, collection_name } = props.schema;
|
||||||
const { activeTab = {}, item = {} } = props;
|
const { activeTab = {}, item = {}, associatedName, associatedKey } = props;
|
||||||
const { association } = activeTab;
|
const { association } = activeTab;
|
||||||
|
|
||||||
const params = {};
|
const params = {};
|
||||||
|
|
||||||
if (association) {
|
if (association) {
|
||||||
params['resourceName'] = association;
|
params['resourceName'] = association;
|
||||||
params['associatedName'] = activeTab.collection_name;
|
params['associatedName'] = associatedName;
|
||||||
params['associatedKey'] = item.itemId;
|
params['associatedKey'] = associatedKey;
|
||||||
} else {
|
} else {
|
||||||
params['resourceName'] = collection_name;
|
params['resourceName'] = collection_name;
|
||||||
params['resourceKey'] = item.itemId;
|
params['resourceKey'] = item.itemId;
|
||||||
|
@ -26,6 +26,7 @@ export function Update(props) {
|
|||||||
{...props}
|
{...props}
|
||||||
reference={drawerRef}
|
reference={drawerRef}
|
||||||
viewName={viewName}
|
viewName={viewName}
|
||||||
|
mode={'update'}
|
||||||
{...params}
|
{...params}
|
||||||
/>
|
/>
|
||||||
<Button type={'primary'} onClick={() => {
|
<Button type={'primary'} onClick={() => {
|
||||||
|
@ -15,7 +15,7 @@ export function Details(props: any) {
|
|||||||
associatedKey,
|
associatedKey,
|
||||||
resourceKey,
|
resourceKey,
|
||||||
} = props;
|
} = props;
|
||||||
const { data = {}, loading } = useRequest(() => {
|
const { data = {}, loading, refresh } = useRequest(() => {
|
||||||
const name = associatedName ? `${associatedName}.${resourceName}` : resourceName;
|
const name = associatedName ? `${associatedName}.${resourceName}` : resourceName;
|
||||||
return api.resource(name).get({
|
return api.resource(name).get({
|
||||||
resourceKey,
|
resourceKey,
|
||||||
@ -26,7 +26,9 @@ export function Details(props: any) {
|
|||||||
const { actions = [], fields = [] } = props.schema;
|
const { actions = [], fields = [] } = props.schema;
|
||||||
return (
|
return (
|
||||||
<Card bordered={false}>
|
<Card bordered={false}>
|
||||||
<Actions {...props} style={{ marginBottom: 14 }} actions={actions}/>
|
<Actions {...props} onFinish={() => {
|
||||||
|
refresh();
|
||||||
|
}} style={{ marginBottom: 14 }} actions={actions}/>
|
||||||
{loading ? <Spin/> : (
|
{loading ? <Spin/> : (
|
||||||
<Descriptions bordered column={1}>
|
<Descriptions bordered column={1}>
|
||||||
{fields.map((field: any) => {
|
{fields.map((field: any) => {
|
||||||
|
@ -27,10 +27,14 @@ export const DrawerForm = forwardRef((props: any, ref) => {
|
|||||||
resourceName,
|
resourceName,
|
||||||
associatedName,
|
associatedName,
|
||||||
associatedKey,
|
associatedKey,
|
||||||
|
onFinish,
|
||||||
} = props;
|
} = props;
|
||||||
|
console.log(associatedKey);
|
||||||
|
const [resourceKey, setResourceKey] = useState(props.resourceKey);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
|
const name = associatedName ? `${associatedName}.${resourceName}` : resourceName;
|
||||||
const { data, run, loading } = useRequest((resourceKey) => {
|
const { data, run, loading } = useRequest((resourceKey) => {
|
||||||
const name = associatedName ? `${associatedName}.${resourceName}` : resourceName;
|
setResourceKey(resourceKey);
|
||||||
return api.resource(name).get({
|
return api.resource(name).get({
|
||||||
resourceKey,
|
resourceKey,
|
||||||
associatedKey,
|
associatedKey,
|
||||||
@ -44,7 +48,7 @@ export const DrawerForm = forwardRef((props: any, ref) => {
|
|||||||
}));
|
}));
|
||||||
const actions = createAsyncFormActions();
|
const actions = createAsyncFormActions();
|
||||||
const { title, fields: properties ={} } = props.schema||{};
|
const { title, fields: properties ={} } = props.schema||{};
|
||||||
console.log({properties});
|
console.log({onFinish});
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
{...props}
|
{...props}
|
||||||
@ -57,8 +61,22 @@ export const DrawerForm = forwardRef((props: any, ref) => {
|
|||||||
title={title}
|
title={title}
|
||||||
footer={[
|
footer={[
|
||||||
<Button type={'primary'} onClick={async () => {
|
<Button type={'primary'} onClick={async () => {
|
||||||
const values = await actions.submit();
|
const { values = {} } = await actions.submit();
|
||||||
console.log(values);
|
console.log(values);
|
||||||
|
if (resourceKey) {
|
||||||
|
await api.resource(name).update({
|
||||||
|
resourceKey,
|
||||||
|
associatedKey,
|
||||||
|
...values,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await api.resource(name).create({
|
||||||
|
associatedKey,
|
||||||
|
...values,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setVisible(false);
|
||||||
|
onFinish && onFinish(values);
|
||||||
}}>提交</Button>
|
}}>提交</Button>
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
@ -64,9 +64,17 @@ export function SimpleTable(props: SimpleTableProps) {
|
|||||||
console.log('rowViewName', {rowViewName})
|
console.log('rowViewName', {rowViewName})
|
||||||
return (
|
return (
|
||||||
<Card bordered={false}>
|
<Card bordered={false}>
|
||||||
<Actions {...props} style={{ marginBottom: 14 }} actions={actions}/>
|
<Actions
|
||||||
|
{...props}
|
||||||
|
style={{ marginBottom: 14 }}
|
||||||
|
actions={actions}
|
||||||
|
onFinish={() => {
|
||||||
|
refresh();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<ViewFactory
|
<ViewFactory
|
||||||
{...props}
|
{...props}
|
||||||
|
mode={'update'}
|
||||||
viewName={rowViewName}
|
viewName={rowViewName}
|
||||||
reference={drawerRef}
|
reference={drawerRef}
|
||||||
/>
|
/>
|
||||||
|
@ -80,7 +80,14 @@ export function Table(props: TableProps) {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Card bordered={false}>
|
<Card bordered={false}>
|
||||||
<Actions {...props} style={{ marginBottom: 14 }} actions={actions}/>
|
<Actions
|
||||||
|
{...props}
|
||||||
|
style={{ marginBottom: 14 }}
|
||||||
|
actions={actions}
|
||||||
|
onFinish={() => {
|
||||||
|
refresh();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<AntdTable
|
<AntdTable
|
||||||
rowKey={rowKey}
|
rowKey={rowKey}
|
||||||
columns={fields2columns(fields)}
|
columns={fields2columns(fields)}
|
||||||
|
@ -45,12 +45,14 @@ export default function ViewFactory(props: ViewProps) {
|
|||||||
associatedKey,
|
associatedKey,
|
||||||
resourceName,
|
resourceName,
|
||||||
viewName,
|
viewName,
|
||||||
|
mode,
|
||||||
reference,
|
reference,
|
||||||
} = props;
|
} = props;
|
||||||
const { data = {}, loading } = useRequest(() => {
|
const { data = {}, loading } = useRequest(() => {
|
||||||
const params = {
|
const params = {
|
||||||
resourceKey: viewName,
|
resourceKey: viewName,
|
||||||
associatedName: associatedName,
|
associatedName: associatedName,
|
||||||
|
mode,
|
||||||
};
|
};
|
||||||
return api.resource(resourceName).getView(params);
|
return api.resource(resourceName).getView(params);
|
||||||
}, {
|
}, {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Database, { ModelCtor } from '@nocobase/database';
|
import Database, { ModelCtor } from '@nocobase/database';
|
||||||
import { getDatabase } from '.';
|
import { getDatabase } from '.';
|
||||||
import BaseModel from '../models/base';
|
import BaseModel from '../models/base';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
describe('base model', () => {
|
describe('base model', () => {
|
||||||
let database: Database;
|
let database: Database;
|
||||||
@ -21,6 +22,11 @@ describe('base model', () => {
|
|||||||
name: 'title',
|
name: 'title',
|
||||||
type: 'virtual',
|
type: 'virtual',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'xyz',
|
||||||
|
type: 'virtual',
|
||||||
|
defaultValue: 'xyz1',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'content',
|
name: 'content',
|
||||||
type: 'virtual',
|
type: 'virtual',
|
||||||
@ -92,6 +98,7 @@ describe('base model', () => {
|
|||||||
bb: 'bb',
|
bb: 'bb',
|
||||||
},
|
},
|
||||||
bcd: 'bbb',
|
bcd: 'bbb',
|
||||||
|
xyz: "xyz1",
|
||||||
arr: [{a: 'a'}, {b: 'b'}],
|
arr: [{a: 'a'}, {b: 'b'}],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -189,4 +196,64 @@ describe('base model', () => {
|
|||||||
});
|
});
|
||||||
expect(test2.get('content')).toBeUndefined();
|
expect(test2.get('content')).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('update', async () => {
|
||||||
|
const t = await TestModel.create({
|
||||||
|
name: 'name1',
|
||||||
|
// xyz: 'xyz',
|
||||||
|
});
|
||||||
|
await t.update({
|
||||||
|
abc: 'abc',
|
||||||
|
});
|
||||||
|
const t2 = await TestModel.findOne({
|
||||||
|
where: {
|
||||||
|
name: 'name1',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(t2.get()).toMatchObject({
|
||||||
|
xyz: 'xyz1',
|
||||||
|
abc: 'abc',
|
||||||
|
key2: 'val2',
|
||||||
|
id: 2,
|
||||||
|
name: 'name1',
|
||||||
|
});
|
||||||
|
await t2.update({
|
||||||
|
abc: 'abcdef',
|
||||||
|
});
|
||||||
|
const t3 = await TestModel.findOne({
|
||||||
|
where: {
|
||||||
|
name: 'name1',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 查询之后更新再重新查询
|
||||||
|
expect(t3.get()).toMatchObject({
|
||||||
|
xyz: 'xyz1',
|
||||||
|
abc: 'abcdef',
|
||||||
|
key2: 'val2',
|
||||||
|
id: 2,
|
||||||
|
name: 'name1',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('update', async () => {
|
||||||
|
const t = await TestModel.create({
|
||||||
|
name: 'name1',
|
||||||
|
xyz: 'xyz',
|
||||||
|
});
|
||||||
|
await t.update({
|
||||||
|
abc: 'abc',
|
||||||
|
});
|
||||||
|
const t2 = await TestModel.findOne({
|
||||||
|
where: {
|
||||||
|
name: 'name1',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(t2.get()).toMatchObject({
|
||||||
|
xyz: 'xyz',
|
||||||
|
abc: 'abc',
|
||||||
|
key2: 'val2',
|
||||||
|
id: 2,
|
||||||
|
name: 'name1',
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -17,7 +17,7 @@ describe('collection hooks', () => {
|
|||||||
const tables = app.database.getTables([]);
|
const tables = app.database.getTables([]);
|
||||||
for (const table of tables) {
|
for (const table of tables) {
|
||||||
const Collection = app.database.getModel('collections');
|
const Collection = app.database.getModel('collections');
|
||||||
await Collection.import(table.getOptions(), { hooks: false });
|
await Collection.import(table.getOptions(), { migrate: false });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ export default {
|
|||||||
name: 'component.tooltip',
|
name: 'component.tooltip',
|
||||||
title: '提示信息',
|
title: '提示信息',
|
||||||
component: {
|
component: {
|
||||||
type: 'string',
|
type: 'textarea',
|
||||||
showInDetail: true,
|
showInDetail: true,
|
||||||
showInForm: true,
|
showInForm: true,
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import CollectionModel from '../models/collection';
|
import CollectionModel from '../models/collection';
|
||||||
|
|
||||||
export default async function (model: CollectionModel) {
|
export default async function (model: CollectionModel, options: any = {}) {
|
||||||
await model.migrate();
|
const { migrate = true } = options;
|
||||||
|
if (migrate) {
|
||||||
|
await model.migrate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import CollectionModel from '../models/collection';
|
import CollectionModel from '../models/collection';
|
||||||
|
|
||||||
export default async function (model: CollectionModel) {
|
export default async function (model: CollectionModel) {
|
||||||
if (!model.get('name')) {
|
model.generateNameIfNull();
|
||||||
model.setDataValue('name', this.generateName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import FieldModel from '../models/field';
|
import FieldModel from '../models/field';
|
||||||
|
|
||||||
export default async function (model: FieldModel) {
|
export default async function (model: FieldModel, options: any = {}) {
|
||||||
// console.log('afterCreate', model.toJSON());
|
const { migrate = true } = options;
|
||||||
await model.migrate();
|
if (migrate) {
|
||||||
|
await model.migrate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,10 @@
|
|||||||
import FieldModel from '../models/field';
|
import FieldModel from '../models/field';
|
||||||
import * as types from '../interfaces/types';
|
import * as types from '../interfaces/types';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
export default async function (model: FieldModel) {
|
export default async function (model: FieldModel) {
|
||||||
const values = model.get();
|
model.generateNameIfNull();
|
||||||
if (!values.name) {
|
if (model.get('interface')) {
|
||||||
values.name = this.generateName();
|
model.setInterface(model.get('interface'));
|
||||||
}
|
}
|
||||||
if (values.interface) {
|
|
||||||
const { options } = types[values.interface];
|
|
||||||
Object.keys(options).forEach(key => {
|
|
||||||
switch (typeof values[key]) {
|
|
||||||
case 'undefined':
|
|
||||||
values[key] = options[key];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'object':
|
|
||||||
values[key] = {
|
|
||||||
...options[key],
|
|
||||||
...values[key]
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
model.set(values, { raw: true });
|
|
||||||
}
|
}
|
||||||
|
@ -453,6 +453,7 @@ export const json = {
|
|||||||
options: {
|
options: {
|
||||||
interface: 'json',
|
interface: 'json',
|
||||||
type: 'json',
|
type: 'json',
|
||||||
|
dottie: true,
|
||||||
component: {
|
component: {
|
||||||
type: 'hidden',
|
type: 'hidden',
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { getDataTypeKey, Model } from '@nocobase/database';
|
import { getDataTypeKey, Model } from '@nocobase/database';
|
||||||
|
import { Utils } from 'sequelize';
|
||||||
|
|
||||||
export class BaseModel extends Model {
|
export class BaseModel extends Model {
|
||||||
|
|
||||||
get additionalAttribute() {
|
get additionalAttribute() {
|
||||||
const tableOptions = this.database.getTable(this.constructor.name).getOptions();
|
const tableOptions = this.database.getTable(this.constructor.name).getOptions();
|
||||||
return _.get(tableOptions, 'additionalAttribute') || 'options';
|
return _.get(tableOptions, 'additionalAttribute') || 'options';
|
||||||
@ -57,19 +59,22 @@ export class BaseModel extends Model {
|
|||||||
return _.get(options, key);
|
return _.get(options, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(key?: any, value?: any, options?: any) {
|
set(key?: any, value?: any, options: any = {}) {
|
||||||
if (typeof key === 'string') {
|
if (typeof key === 'string') {
|
||||||
// 不处理关系数据
|
// 不处理关系数据
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (_.get(this.constructor.associations, key)) {
|
if (_.get(this.constructor.associations, key)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
// 如果是 object 数据,merge 处理
|
// 如果是 object 数据,merge 处理
|
||||||
if (_.isPlainObject(value)) {
|
if (_.isPlainObject(value)) {
|
||||||
value = _.merge(this.get(key)||{}, value);
|
// @ts-ignore
|
||||||
|
value = Utils.merge(this.get(key)||{}, value);
|
||||||
}
|
}
|
||||||
const [column, ...path] = key.split('.');
|
const [column, ...path] = key.split('.');
|
||||||
this.changed(column, true);
|
if (!options.raw) {
|
||||||
|
this.changed(column, true);
|
||||||
|
}
|
||||||
if (this.hasSetAttribute(column)) {
|
if (this.hasSetAttribute(column)) {
|
||||||
if (!path.length) {
|
if (!path.length) {
|
||||||
return super.set(key, value, options);
|
return super.set(key, value, options);
|
||||||
@ -81,7 +86,9 @@ export class BaseModel extends Model {
|
|||||||
// 如果未设置 attribute,存到 additionalAttribute 里
|
// 如果未设置 attribute,存到 additionalAttribute 里
|
||||||
const opts = this.get(this.additionalAttribute, options) || {};
|
const opts = this.get(this.additionalAttribute, options) || {};
|
||||||
_.set(opts, key, value);
|
_.set(opts, key, value);
|
||||||
this.changed(this.additionalAttribute, true);
|
if (!options.raw) {
|
||||||
|
this.changed(this.additionalAttribute, true);
|
||||||
|
}
|
||||||
return super.set(this.additionalAttribute, opts, options);
|
return super.set(this.additionalAttribute, opts, options);
|
||||||
}
|
}
|
||||||
return super.set(key, value, options);
|
return super.set(key, value, options);
|
||||||
@ -94,7 +101,8 @@ export class BaseModel extends Model {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if (_.isPlainObject(value)) {
|
if (_.isPlainObject(value)) {
|
||||||
value = _.merge(this.get(key)||{}, value);
|
// @ts-ignore
|
||||||
|
value = Utils.merge(this.get(key)||{}, value);
|
||||||
}
|
}
|
||||||
const [column, ...path] = key.split('.');
|
const [column, ...path] = key.split('.');
|
||||||
this.changed(column, true);
|
this.changed(column, true);
|
||||||
|
@ -1,10 +1,36 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import BaseModel from './base';
|
import BaseModel from './base';
|
||||||
import { TableOptions } from '@nocobase/database';
|
import { TableOptions } from '@nocobase/database';
|
||||||
import { SaveOptions, Utils } from 'sequelize';
|
import { SaveOptions } 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')}`;
|
||||||
|
}
|
||||||
|
|
||||||
export class CollectionModel extends BaseModel {
|
export class CollectionModel extends BaseModel {
|
||||||
|
|
||||||
|
generateName() {
|
||||||
|
this.set('name', generateCollectionName());
|
||||||
|
}
|
||||||
|
|
||||||
|
generateNameIfNull() {
|
||||||
|
if (!this.get('name')) {
|
||||||
|
this.generateName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 name 获取 collection
|
* 通过 name 获取 collection
|
||||||
*
|
*
|
||||||
@ -14,22 +40,6 @@ export class CollectionModel extends BaseModel {
|
|||||||
return this.findOne({ where: { name } });
|
return this.findOne({ where: { name } });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成随机数据库表名
|
|
||||||
*
|
|
||||||
* 策略:暂时使用 3+2
|
|
||||||
* 1. 自增 id
|
|
||||||
* 2. 随机字母
|
|
||||||
* 3. 时间戳
|
|
||||||
* 4. 转拼音
|
|
||||||
* 5. 常见词翻译
|
|
||||||
*
|
|
||||||
* @param title 显示的名称
|
|
||||||
*/
|
|
||||||
static generateName(title?: string): string {
|
|
||||||
return `t_${Date.now().toString(36)}_${Math.random().toString(36).replace('0.', '').slice(-4).padStart(4, '0')}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 迁移
|
* 迁移
|
||||||
*/
|
*/
|
||||||
@ -80,12 +90,8 @@ export class CollectionModel extends BaseModel {
|
|||||||
...item,
|
...item,
|
||||||
sort,
|
sort,
|
||||||
}));
|
}));
|
||||||
for (const item of items[key]) {
|
|
||||||
await collection[`create${_.upperFirst(Utils.singularize(key))}`](item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// updateAssociations 有 BUG
|
await collection.updateAssociations(items, options);
|
||||||
// await collection.updateAssociations(items, options);
|
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,30 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import BaseModel from './base';
|
import BaseModel from './base';
|
||||||
import { FieldOptions } from '@nocobase/database';
|
import { FieldOptions } from '@nocobase/database';
|
||||||
|
import * as types from '../interfaces/types';
|
||||||
|
import { Utils } from 'sequelize';
|
||||||
|
|
||||||
|
export function generateFieldName(title?: string): string {
|
||||||
|
return `f_${Math.random().toString(36).replace('0.', '').slice(-4).padStart(4, '0')}`;
|
||||||
|
}
|
||||||
|
|
||||||
export class FieldModel extends BaseModel {
|
export class FieldModel extends BaseModel {
|
||||||
static generateName(title?: string): string {
|
|
||||||
return `f_${Math.random().toString(36).replace('0.', '').slice(-4).padStart(4, '0')}`;
|
generateName() {
|
||||||
|
this.set('name', generateFieldName());
|
||||||
|
}
|
||||||
|
|
||||||
|
generateNameIfNull() {
|
||||||
|
if (!this.get('name')) {
|
||||||
|
this.generateName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setInterface(value) {
|
||||||
|
const { options } = types[value];
|
||||||
|
// @ts-ignore
|
||||||
|
const values = Utils.merge(options, this.get());
|
||||||
|
this.set(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOptions(): Promise<FieldOptions> {
|
async getOptions(): Promise<FieldOptions> {
|
||||||
|
Loading…
Reference in New Issue
Block a user