feat: add virtual attribute geter & setter support (#27)

This commit is contained in:
chenos 2020-12-01 23:38:10 +08:00 committed by GitHub
parent befe5661f8
commit b6cb185380
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 16 deletions

View File

@ -17,6 +17,31 @@ describe('base model', () => {
name: 'name',
type: 'string',
},
{
name: 'title',
type: 'virtual',
},
{
name: 'content',
type: 'virtual',
set(val) {
// 留空
}
},
{
name: 'key1',
type: 'virtual',
set(val) {
this.setDataValue('options.key1', `111${val}111`);
}
},
{
name: 'key2',
type: 'virtual',
get() {
return 'val2';
}
},
{
type: 'json',
name: 'component',
@ -143,4 +168,25 @@ describe('base model', () => {
arr: [{a: 'a'}, {b: 'b'}],
});
});
it.only('update virtual attribute', async () => {
await test.update({
title: 'xxx', // 虚拟字段没 set 转存 options
content: 'content123', // set 留空,这个 key 什么也不做
key1: 'val1', // 走 set 方法
});
// 重新获取再验证
const test2 = await TestModel.findByPk(test.id);
expect(test2.get()).toMatchObject({
abc: { aa: 'aa', bb: 'bb' },
bcd: 'bbb',
name: '123',
component: { a: 'a', b: 'b' },
arr: [{a: 'a'}, {b: 'b'}],
title: 'xxx',
key2: 'val2', // key2 为 get 方法取的
key1: '111val1111',
});
expect(test2.get('content')).toBeUndefined();
});
});

View File

@ -50,7 +50,7 @@ export default {
{
interface: 'string',
type: 'virtual',
name: 'options.icon',
name: 'icon',
title: '图标',
component: {
type: 'string',
@ -62,7 +62,7 @@ export default {
{
interface: 'radio',
type: 'virtual',
name: 'options.defaultView',
name: 'defaultView',
title: '默认视图',
defaultValue: 'table',
dataSource: [
@ -80,7 +80,7 @@ export default {
{
interface: 'radio',
type: 'virtual',
name: 'options.mode',
name: 'mode',
title: '表格模式',
defaultValue: 'default',
dataSource: [
@ -99,7 +99,7 @@ export default {
{
interface: 'radio',
type: 'virtual',
name: 'options.defaultPerPage',
name: 'defaultPerPage',
title: '每页显示几行数据',
defaultValue: 50,
dataSource: [
@ -116,7 +116,7 @@ export default {
{
interface: 'boolean',
type: 'virtual',
name: 'options.draggable',
name: 'draggable',
title: '支持拖拽数据排序',
showInForm: true,
showInDetail: true,

View File

@ -62,7 +62,7 @@ export default {
{
interface: 'subTable',
type: 'virtual',
name: 'options.dataSource',
name: 'dataSource',
title: '可选项',
component: {
type: 'table',

View File

@ -63,7 +63,7 @@ export default {
{
interface: 'string',
type: 'virtual',
name: 'options.association',
name: 'association',
title: '相关数据表',
component: {
type: 'string',

View File

@ -1,5 +1,5 @@
import _ from 'lodash';
import { Model } from '@nocobase/database';
import { getDataTypeKey, Model } from '@nocobase/database';
export class BaseModel extends Model {
get additionalAttribute() {
@ -7,11 +7,28 @@ export class BaseModel extends Model {
return _.get(tableOptions, 'additionalAttribute') || 'options';
}
hasGetAttribute(key: string) {
const attribute = this.rawAttributes[key];
// virtual 如果有 get 方法就直接走 get
if (attribute && attribute.type && getDataTypeKey(attribute.type) === 'VIRTUAL') {
return !!attribute.get;
}
return !!attribute;
}
hasSetAttribute(key: string) {
const attribute = this.rawAttributes[key];
// virtual 如果有 set 方法就直接走 set
if (attribute && attribute.type && getDataTypeKey(attribute.type) === 'VIRTUAL') {
return !!attribute.set;
}
return !!attribute;
}
get(key?: any, options?: any) {
if (typeof key === 'string') {
const [column, ...path] = key.split('.');
const attribute = this.rawAttributes[column];
if (attribute) {
if (this.hasGetAttribute(column)) {
const value = super.get(column, options);
if (path.length) {
return _.get(value, path);
@ -29,8 +46,7 @@ export class BaseModel extends Model {
getDataValue(key: any) {
const [column, ...path] = key.split('.');
const attribute = this.rawAttributes[column];
if (attribute) {
if (this.hasGetAttribute(column)) {
const value = super.getDataValue(column);
if (path.length) {
return _.get(value, path);
@ -54,8 +70,7 @@ export class BaseModel extends Model {
}
const [column, ...path] = key.split('.');
this.changed(column, true);
const attribute = this.rawAttributes[column];
if (attribute) {
if (this.hasSetAttribute(column)) {
if (!path.length) {
return super.set(key, value, options);
}
@ -83,8 +98,7 @@ export class BaseModel extends Model {
}
const [column, ...path] = key.split('.');
this.changed(column, true);
const attribute = this.rawAttributes[column];
if (attribute) {
if (this.hasSetAttribute(column)) {
if (!path.length) {
return super.setDataValue(key, value);
}