2020-12-01 20:11:39 +08:00
|
|
|
|
import _ from 'lodash';
|
2020-12-01 23:38:10 +08:00
|
|
|
|
import { getDataTypeKey, Model } from '@nocobase/database';
|
2020-12-09 20:45:15 +08:00
|
|
|
|
import { merge } from '../utils';
|
2020-12-01 20:11:39 +08:00
|
|
|
|
|
2020-12-07 23:24:43 +08:00
|
|
|
|
export function generateName(title?: string): string {
|
|
|
|
|
return `${Math.random().toString(36).replace('0.', '').slice(-4).padStart(4, '0')}`;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 20:11:39 +08:00
|
|
|
|
export class BaseModel extends Model {
|
2020-12-04 21:09:39 +08:00
|
|
|
|
|
2020-12-07 23:24:43 +08:00
|
|
|
|
generateName() {
|
|
|
|
|
this.set('name', generateName());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
generateNameIfNull() {
|
|
|
|
|
if (!this.get('name')) {
|
|
|
|
|
this.generateName();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 20:11:39 +08:00
|
|
|
|
get additionalAttribute() {
|
|
|
|
|
const tableOptions = this.database.getTable(this.constructor.name).getOptions();
|
|
|
|
|
return _.get(tableOptions, 'additionalAttribute') || 'options';
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 23:38:10 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 20:11:39 +08:00
|
|
|
|
get(key?: any, options?: any) {
|
|
|
|
|
if (typeof key === 'string') {
|
|
|
|
|
const [column, ...path] = key.split('.');
|
2020-12-01 23:38:10 +08:00
|
|
|
|
if (this.hasGetAttribute(column)) {
|
2020-12-01 20:11:39 +08:00
|
|
|
|
const value = super.get(column, options);
|
|
|
|
|
if (path.length) {
|
|
|
|
|
return _.get(value, path);
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
return _.get(super.get(this.additionalAttribute, options) || {}, key);
|
|
|
|
|
}
|
|
|
|
|
const data = super.get();
|
|
|
|
|
return {
|
|
|
|
|
...(data[this.additionalAttribute]||{}),
|
|
|
|
|
..._.omit(data, [this.additionalAttribute]),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getDataValue(key: any) {
|
|
|
|
|
const [column, ...path] = key.split('.');
|
2020-12-01 23:38:10 +08:00
|
|
|
|
if (this.hasGetAttribute(column)) {
|
2020-12-01 20:11:39 +08:00
|
|
|
|
const value = super.getDataValue(column);
|
|
|
|
|
if (path.length) {
|
|
|
|
|
return _.get(value, path);
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
const options = super.getDataValue(this.additionalAttribute) || {};
|
|
|
|
|
return _.get(options, key);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 21:09:39 +08:00
|
|
|
|
set(key?: any, value?: any, options: any = {}) {
|
2020-12-01 20:11:39 +08:00
|
|
|
|
if (typeof key === 'string') {
|
|
|
|
|
// 不处理关系数据
|
2020-12-04 21:09:39 +08:00
|
|
|
|
// @ts-ignore
|
2020-12-01 20:11:39 +08:00
|
|
|
|
if (_.get(this.constructor.associations, key)) {
|
2020-12-11 10:37:43 +08:00
|
|
|
|
return super.set(key, value, options);
|
2020-12-01 20:11:39 +08:00
|
|
|
|
}
|
|
|
|
|
// 如果是 object 数据,merge 处理
|
|
|
|
|
if (_.isPlainObject(value)) {
|
2020-12-13 00:09:25 +08:00
|
|
|
|
// TODO 需要改进 JSON 字段的内部处理逻辑,暂时这里跳过了特殊的 filter 字段
|
|
|
|
|
if (key !== 'filter') {
|
|
|
|
|
// console.log(key, value);
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
value = merge(this.get(key)||{}, value);
|
|
|
|
|
}
|
2020-12-01 20:11:39 +08:00
|
|
|
|
}
|
|
|
|
|
const [column, ...path] = key.split('.');
|
2020-12-04 21:09:39 +08:00
|
|
|
|
if (!options.raw) {
|
|
|
|
|
this.changed(column, true);
|
|
|
|
|
}
|
2020-12-01 23:38:10 +08:00
|
|
|
|
if (this.hasSetAttribute(column)) {
|
2020-12-01 20:11:39 +08:00
|
|
|
|
if (!path.length) {
|
|
|
|
|
return super.set(key, value, options);
|
|
|
|
|
}
|
|
|
|
|
const values = this.get(column, options) || {};
|
|
|
|
|
_.set(values, path, value);
|
|
|
|
|
return super.set(column, values, options);
|
|
|
|
|
}
|
|
|
|
|
// 如果未设置 attribute,存到 additionalAttribute 里
|
|
|
|
|
const opts = this.get(this.additionalAttribute, options) || {};
|
|
|
|
|
_.set(opts, key, value);
|
2020-12-04 21:09:39 +08:00
|
|
|
|
if (!options.raw) {
|
|
|
|
|
this.changed(this.additionalAttribute, true);
|
|
|
|
|
}
|
2020-12-01 20:11:39 +08:00
|
|
|
|
return super.set(this.additionalAttribute, opts, options);
|
|
|
|
|
}
|
|
|
|
|
return super.set(key, value, options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setDataValue(key: any, value: any) {
|
|
|
|
|
// 不处理关系数据
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
if (_.get(this.constructor.associations, key)) {
|
2020-12-11 10:37:43 +08:00
|
|
|
|
return super.setDataValue(key, value);
|
2020-12-01 20:11:39 +08:00
|
|
|
|
}
|
|
|
|
|
if (_.isPlainObject(value)) {
|
2020-12-04 21:09:39 +08:00
|
|
|
|
// @ts-ignore
|
|
|
|
|
value = Utils.merge(this.get(key)||{}, value);
|
2020-12-01 20:11:39 +08:00
|
|
|
|
}
|
|
|
|
|
const [column, ...path] = key.split('.');
|
|
|
|
|
this.changed(column, true);
|
2020-12-01 23:38:10 +08:00
|
|
|
|
if (this.hasSetAttribute(column)) {
|
2020-12-01 20:11:39 +08:00
|
|
|
|
if (!path.length) {
|
|
|
|
|
return super.setDataValue(key, value);
|
|
|
|
|
}
|
|
|
|
|
const values = this.get(column) || {};
|
|
|
|
|
_.set(values, path, value);
|
|
|
|
|
return super.setDataValue(column, values);
|
|
|
|
|
}
|
|
|
|
|
const opts = this.get(this.additionalAttribute) || {};
|
|
|
|
|
_.set(opts, key, value);
|
|
|
|
|
this.changed(this.additionalAttribute, true);
|
|
|
|
|
return super.setDataValue(this.additionalAttribute, opts);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default BaseModel;
|